@interface Person : NSObject
@property (nonatomic, copy) NSString *givenName;
@property (nonatomic, copy) NSString *familyName;
@property (nonatomic, strong) NSNumber *yearsOld;
@property (nonatomic, strong) NSNumber *heightInInches;
@property (nonatomic, copy) NSString *languageKnown;
@property (nonatomic, copy) NSString *phone;
@property (nonatomic, copy) NSString *state;
@property (nonatomic, copy) NSString *city;
@property (nonatomic, copy) NSString *zip;
@property (nonatomic, copy) NSString *ssn;
@property (nonatomic, strong) NSDate *birthDate;
@property (nonatomic, strong) NSDate *startDate;
@end
...
NSDictionary *json = @{
@"firstName" : @"John",
@"lastName" : @"Jacob",
@"age" : @25,
@"heightInInches" : @68.5,
@"phoneNumber" : @"415-555-1234",
@"state" : @"California",
@"city" : @"Daly City",
@"zip" : @94015,
@"socialSecurityNumber" : [NSNull null],
@"birthDate" : @"11-08-1988",
@"startDate" : @"Nov 05 2012"
};
Person *person = [Person new];
person.givenName = [json objectForKey:@"firstName"];
person.familyName = [json objectForKey:@"lastName"];
person.yearsOld = [json objectForKey:@"age"];
person.heightInInches = [json objectForKey:@"heightInInches"];
person.phone = [json objectForKey:@"phoneNumber"];
person.state = [json objectForKey:@"state"];
person.city = [json objectForKey:@"city"];
NSNumber *zipNumber = [json objectForKey:@"zip"];
if([zipNumber isKindOfClass:[NSNumber class]]
person.zip = [zipNumber stringValue];
NSString *socialSecurityNumber = [json objectForKey:@"socialSecurityNumber"];
if([socialSecurityNumber isKindOfClass:[NSString class]])
person.ssn = socialSecurityNumber;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSString *birthDateString = [json objectForKey:@"birthDate"];
if([birthDateString isKindOfClass:[NSString class]]) {
[dateFormatter setDateFormat:@"MM-dd-yyyy"];
person.birthDate = [dateFormatter dateFromString:birthDateString];
}
NSString *startDateString = [json objectForKey:@"startDate"];
if([startDateString isKindOfClass:[NSString class]]) {
[dateFormatter setDateFormat:@"MMM dd yyyy"];
person.startDate = [dateFormatter dateFromString:startDateString];
}
Person *person = [Person new];
[[RPJSONMapper sharedInstance] mapJSONValuesFrom:json toInstance:person usingMapping:@{
@"firstName" : @"givenName",
@"lastName" : @"familyName",
@"age" : @"yearsOld",
@"heightInInches" : @"heightInInches",
@"phoneNumber" : @"phone",
@"state" : @"state",
@"city" : @"city",
@"zip" : [[RPJSONMapper sharedInstance] boxValueAsNSStringIntoPropertyWithName:@"zip"],
@"socialSecurityNumber" : @"ssn",
@"birthDate" : [[RPJSONMapper sharedInstance] boxValueAsNSDateIntoPropertyWithName:@"birthDate" usingDateFormat:@"MM-dd-yyyy"],
@"startDate" : [[RPJSONMapper sharedInstance] boxValueAsNSDateIntoPropertyWithName:@"startDate" usingDateFormat:@"MMM dd yyyy"]
}];
映射字典中的第一个键值对是 @"firstName" : @"givenName"
。此映射将 JSON 字典中 "firstName"
的值 ("John") 设置为 person
的 @property (nonatomic, copy) NSString *givenName
。
另一个键值对是 @"zip" : [[RPJSONMapper sharedInstance] boxValueAsNSStringIntoPropertyWithName:@"zip"]
。此映射从 JSON 字典中检索 "zip"
的值 (@94015),获取其字符串值 (@"94015"),然后将其设置到 person
的 @property (nonatomic, copy) NSString *zip
。我们将其封装为 NSString,因为我们不能将 NSNumber 存储到 NSString 中。
第二种类型的封装是针对 NSDates,通过键值对 @"birthDate" : [[RPJSONMapper sharedInstance] boxValueAsNSDateIntoPropertyWithName:@"birthDate" usingDateFormat:@"MM-dd-yyyy"]
进行说明。就像其他两个键值对一样,它从 JSON 字典中获取 "birthDate"
的值 (@"11-08-1988"),使用日期格式 (@"MM-dd-yyyy") 获取其 NSDate 值,然后将其设置到 @property (nonatomic, strong) NSDate *birthDate
。底层的 NSDateFormatter 是 RPJSONMapper 的一个实例变量,仅在 @synchronized 调用中访问(因此它是多线程安全的)。
@interface PowerPack : NSObject
@property (nonatomic, copy) NSString *supercharger;
@property (nonatomic, copy) NSString *turbocharger;
@end
...
NSDictionary *json = @{
@"supercharger" : [NSNull null],
@"turbocharger" : [NSNull null]
};
PowerPack *mustangPowerPack = [PowerPack new];
[[RPJSONMapper sharedInstance] mapJSONValuesFrom:json toInstance:mustangPowerPack usingMapping:@{
@"supercharger" : @"supercharger", // No need to wrap setObject:forKey: calls with if statements anymore!
@"turbocharger" : @"turbocharger"
}];
@interface Developer : NSObject
@property (nonatomic, strong) NSNumber *bench;
@property (nonatomic, strong) NSNumber *squat;
@property (nonatomic, strong) NSNumber *deadlift;
@end
...
NSDictionary *json = @{
@"bench" : @"225",
@"squat" : @"315",
@"deadlift" : @"405"
};
StrengthLog *log = [StrengthLog new];
[[RPJSONMapper sharedInstance] mapJSONValuesFrom:json toInstance:log usingMapping:@{
@"bench" : @"bench", // Forgot to write boxValueAsNSNumberIntoPropertyWithName:?
@"squat" : @"squat", // Don't worry!
@"deadlift" : @"deadlift" // It's done automatically!
}];
NSDictionary *json = @{...};
NSArray *jsonArray = @[json, json, json];
// Before
NSMutableArray *people = [NSMutableArray array];
if([jsonArray isKindOfClass:[NSArray class]]) {
for(NSDictionary *subJSON in jsonArray) {
Person *person = [Person new];
[[RPJSONMapper sharedInstance] mapJSONValuesFrom:json toInstance:person usingMapping:@{...}];
[people addObject:person];
}
}
// After
people = [[RPJSONMapper sharedInstance] objectsFromJSONArray:jsonArray withInstantiationBlock:^id { return [Person new];} usingMapping:@{...}];
NSDictionary *largeJSON = @{
@"Animals" : @[
@{
@"Dog" : @{}
},
@{
@"Cat" : @{
@"Babies" : @[
@{},
@{
@"Runt" : @{
@"Name" : @"Bobby",
@"Age" : @"Kitten"
}
}
]
}
},
@{
@"Bird" : @{}
}
]
};
// Before
id childJSON = [largeJSON objectForKey:@"Animals"];
if([childJSON isKindOfClass:[NSArray class]] && [childJSON count] > 1) {
childJSON = [childJSON objectAtIndex:1];
if([childJSON isKindOfClass:[NSDictionary class]] && [childJSON objectForKey:@"Cat"]) {
childJSON = [childJSON objectForKey:@"Cat"];
if([childJSON isKindOfClass:[NSDictionary class]] && [childJSON objectForKey:@"Babies"]) {
childJSON = [childJSON objectForKey:@"Babies"];
if([childJSON isKindOfClass:[NSArray class]] && [childJSON count] > 1) {
childJSON = [childJSON objectAtIndex:1];
}
}
}
}
// After
childJSON = [[RPJSONMapper sharedInstance] childJSONInJSON:largeJSON usingPath:@[@"Animals", @1, @"Cat", @"Babies", @1]];
NSDateFormatters 的实例化花费很长时间,因此我们要小心它们的数量
或者