早先我们设计一个Model的时候其实就是将一个字典NSDictionary中的Value有针对性的一个一个取出然后赋值;
eg:
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”];
当然我们有更好的方法,例如有很多第三方的解析库,这里我们使用JSONModel来进行JSON的实例化.
##Modle属性命名的注意地方
- 我们只需要设置对应的Property熟悉即可,这个属性的命名 可以严格按照NSDictionary中的key名对应。
eg:
{
“id” : 1,
“name”: Jon,
}
@interface MyModel: JSONModel
@property (strong, nonatomic) NSString* id;
@property (strong, nonatomic) NSString* name;
@end
- 也可以自己自由命名Property 属性名,不过要在实现方法里实现方法:+ (JSONKeyMapper*)keyMapper
{
“id” : 1,
“name”: Jon,
}
@interface MyModel: JSONModel
@property (strong, nonatomic) NSString* uid;
@property (strong, nonatomic) NSString* username;
@end
#import “MyModel.h”
@implementation MyModel
+ (JSONKeyMapper*)keyMapper {
NSDictionary *map = @{ @“id”: @“uid”, @“name”: @“username” };
return [[JSONKeyMapper alloc] initWithDictionary:map];
}
@end
##属性命名类型
在我们不实用JSONModel,自己定义一个模型的时候当你要声明类型的时候还需要在实现方法里进行类型转换,比如
@property (nonatomic, assign) NSInteger id;;
self.id = [jsonDict objectForKey:@“id”] IntegerValue];
使用JSONModel的时候可以不必关心实现方法,你只管声明你需要的数据类型即可:
{
“purchaseDate” : “2012-11-26T10:00:01+02:00”,
“blogURL” : “http://www.touch-code-magazine.com”
}
@interface SmartModel: JSONModel
@property (strong, nonatomic) NSDate* purchaseDate;
@property (strong, nonatomic) NSURL* blogUrl;
@end
ps:当然如果你强制讲一个本是NSString的文笔声明为一个int 这种问题我们不做讨论。
##多层封装和对象
- 对于一个NSDictionary如果一个value也是一个NSDictionary,那么如果你或许会考虑将这个子NSDictionary声明为一个对象类.
{
“idImage”: 1,
“name”: “house.jpg”,
“copyright”: {“author”:”Marin Todorov”, “year”:2012}
}
@interface CopyModel: JSONModel
@property (strong, nonatomic) NSString* author;
@property (assign, nonatomic) int year;
@end
#import “CopyModel.h”
@interface ImageModel: JSONModel
@property (assign, nonatomic) int idImage;
@property (strong, nonatomic) NSString* name;
@property (strong, nonatomic) CopyModel* copyright;
@end
上面的例子就是这样的一个情况,当然每个类的实现方法都按照自己的声明进行自由实现。
- 那么如果这个value是一个包含字典的数组,例如:
{
“idImage”: 1,
“name”: “house.jpg”,
“copyrights”: [{“author”:”Marin Todorov”, “year”:2012},{“author”:”Marin Todorov”, “year”:2012},{“author”:”Marin Todorov”, “year”:2012},...]
}
@protocol CopyModel @end
@interface CopyModel: JSONModel
@property (strong, nonatomic) NSString* author;
@property (assign, nonatomic) int year;
@end
#import “CopyModel.h”
@interface ImageModel: JSONModel
@property (assign, nonatomic) int idImage;
@property (strong, nonatomic) NSString* name;
@property (strong, nonatomic) NSArray<CopyModel>* copyrights;
@end
上面的情况 要注意的地方是
@protocol CopyModel @end
这个协议是为了匹配这个对象命名的如果没有则会提示报错。
###将下一层属性提到上一层解析
eg
{
“order_id”: 104,
“order_details” : [
{
“name”: “Product#1”,
“price”: {
“usd”: 12.95
}
}
]
}
对于上面的这样一个JSON 你想把价格_usd_提到上一个对象
可以使用 *.*联系到一起
@interface OrderModel : JSONModel
@property (assign, nonatomic) int id;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSString* productName;
@end
@implementation OrderModel
+(JSONKeyMapper*)keyMapper
{
return [[JSONKeyMapper alloc] initWithDictionary:@{
@“order_id”: @“id”,
@“order_details.name”: @“productName”,
@“order_details.price.usd”: @“price”
}];
}
@end
##可选属性
在这样的一个场景,当API返回的接口中某个字段不是必选返回的时候,既有值的时候返回,没有的时候这个key就没有,还有一种情况是返回的值是一个空对象, 这种情况下,如果我们上上面的写法声明属性会发现JSONModel无法解析,这时候就需要用到 Optional。
eg:
//this property is required
@property (strong, nonatomic) NSString* string;
//this one’s optional
@property (strong, nonatomic) NSNumber<Optional>* number;
##忽略属性
对于一些属性可以忽略解析的,可以使用*Ignore_进行忽略
{
“id”: “123”,
“name”: null
}
@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString<Ignore>* customProperty;
@end
@implementation ProductModel
@end
当然也可以在实现方法里复写类方法
@implementation ProductModel
+(BOOL)propertyIsOptional:(NSString*)propertyName
{
if ([propertyName isEqualToString:@“name”]) {
return YES;
}
return NO;
}
@end