JSONModel is a data model framework for iOS and OSX. It‘s written in Objective-C and helps you in several different ways.You can read more about its key features below:
self.id = [jsonDict objectForKey:@"id"];
self.name = [jsonDict objectForKey:@"name"];
self.profileImageBig = [jsonDict objectForKey:@"profile_image_big"];
self.profileImageSmall = [jsonDict objectForKey:@"profile_image_small"];
self.profileImageSquare = [jsonDict objectForKey:@"profile_image_square"];
self.firstName = [jsonDict objectForKey:@"firstName"];
self.familyName = [jsonDict objectForKey:@"familyName"];
self.age = [jsonDict objectForKey:@"age"];
What sucks about this code is that you first need to declare all you properties in your interface file and then go ahead and write init method for your model that just reads the JSON through and copy all the values over to your propertis.@interface MyModel: JSONModel
@property (strong, nonatomic) NSString* id;
@property (strong, nonatomic) NSString* name;
(etc...)
@end
JSONModel‘s inherited initWithDictionary: method will take care to match incoming JSON keys with your model‘s properties, and copy over the matching ones. No need of any code in your implementation file.self.profileURL = [jsonDict objectForKey:@"profileURL"]; //TODO: what to do if there‘s no url in the JSON? should we handle this somehow? if (!self.profileURL) NSLog(@"something‘s broken with the json API");When you write a model the traditional way, you also need to validate whether the keys your model need are found in the incoming JSON.
//this property is required @property (strong, nonatomic) NSString* string; //this one‘s optional @property (strong, nonatomic) NSNumber<Optional>* number;
if (jsonDict[@"name"])
labelName.text = jsonDict[@"name"];
else
[self showErrorMessageAndBailout];
if (jsonDict[@"age"])
labelAge.text = jsonDict[@"age"];
else
[self showErrorMessageAndBailout];
Do you notice the problem? The code reads and validates and data, AND in the same time updates the user interface. SimpleModel* model = [[SimpleModel alloc] initWithString:@"...json here..." error:nil];
And here‘s how you make an instance of model, which contains other models, and has JSON data converted to custom classes when read:
SuperComplicatedModel* model = [[SuperComplicatedModel alloc] initWithString:@"...json here..." error:nil];
And here is how you read a list of 100 models, as each of them is the described above model:
NSArray* models = [SuperComplicatedModel arrayOfObjectsFromDictionaries: jsonDatas error:nil];
As you see - instantiation is always one-liner, which you can comfortably error handle.{
"first" : 1,
"second": 35,
"third" : 10034,
"fourth": 10000
}
You have four keys and their values are numbers, therefore you get the same old NSNumber back when you parse the JSON yourself.@interface NumbersModel: JSONModel
@property (assign, nonatomic) short first;
@property (assign, nonatomic) double second;
@property (strong, nonatomic) NSNumber* third;
@property (strong, nonatomic) NSString* fourth;
@end
Again - no implementation code needed for this to work!{
"purchaseDate" : "2012-11-26T10:00:01+02:00",
"blogURL" : "http://www.touch-code-magazine.com"
}
This JSON includes a date in W3C format (widely used in JSON APIs), but it comes to your iOS app as a string, because JSON does not have a data type "date".@interface SmartModel: JSONModel
@property (strong, nonatomic) NSDate* purchaseDate;
@property (strong, nonatomic) NSURL* blogUrl;
@end
JSONModel see that there‘s a mismatch between the incoming types and your model‘s properties types, and that when the transformers kick in and convert the values. In the end you just use your properties as normal. Smooth.@interface JSONValueTransformer(UIColor)
-(UIColor*)UIColorFromNSString:(NSString*)string;
-(id)JSONObjectFromUIColor:(UIColor*)color;
@end
This example adds transformer for a UIColor* property, which gets its value from a HEX encoded color coming in as a string. The first method you declare is named like so:-(YourPropertyClass*)YourPropertyClassFromJSONObjectClass:(JSONObjectClass*)name;
Therefore since the HEX color comes from JSON as an NSString, and your property is of type UIColor* your method name should be:
-(UIColor*)UIColorFromNSString:(NSString*)string;
It makes sense? It‘s easy? Yes - I agree.{
"idImage": 1,
"name": "house.jpg",
"copyright": {"author":"Marin Todorov", "year":2012}
}
It‘s pretty simple to define your models for this JSON. Just have first your copyright model defined:
@interface CopyModel: JSONModel
@property (strong, nonatomic) NSString* author;
@property (assign, nonatomic) int year;
@end
And then define your Image model, which contains the copyright model, like so:
#import "CopyModel.h"
@interface ImageModel: JSONModel
@property (assign, nonatomic) int idImage;
@property (strong, nonatomic) NSString* name;
@property (strong, nonatomic) CopyModel* copyright;
@end
That‘s it. When you initialize an instance of the ImageModel, it will see that one of the properties is a JSONModel itself, and will parse properly the JSON input. Boom!
@property (strong, nonatomic) NSArray<TweetModel>* tweets;
And for that to work you also need to add a protocol definition to your model interface file, and the protocol name should match your model name. So for a model called TweetModel (as in the example above), add in TweetModel.h:
@protocol TweetModel @end
That‘s it. Now your top model can cascade inside the JSON structure and read through multilevel structures.//load from file NSDictionary* object = [NSDictionary dictionaryWithContentsOfFile:filePath]; //initialize model with data data = [[MyDataModel alloc] initWithDictionary: object];And saving it back to the disc:
//save to disc [[data toDictionary] writeToFile:filePath atomically:YES];
原文:http://www.cnblogs.com/Soulland/p/4458738.html