2014-01-24 26 views
9

我有一个JSON对象:如何NSDictionary中转换为自定义对象

@interface Order : NSObject 

@property (nonatomic, retain) NSString *OrderId; 
@property (nonatomic, retain) NSString *Title; 
@property (nonatomic, retain) NSString *Weight; 

- (NSMutableDictionary *)toNSDictionary; 
... 

- (NSMutableDictionary *)toNSDictionary 
{ 

    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 
    [dictionary setValue:self.OrderId forKey:@"OrderId"]; 
    [dictionary setValue:self.Title forKey:@"Title"]; 
    [dictionary setValue:self.Weight forKey:@"Weight"]; 

    return dictionary; 
} 

在字符串是这样的:

{ 
    "Title" : "test", 
    "Weight" : "32", 
    "OrderId" : "55" 
} 

我得到的字符串JSON与代码:

NSMutableDictionary* str = [o toNSDictionary]; 

    NSError *writeError = nil; 

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:str options:NSJSONWritingPrettyPrinted error:&writeError]; 
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 

现在我需要从JSON字符串创建和映射对象

NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 
    NSError *e; 
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e]; 

这会返回填充的NSDictionary。 我该怎么做才能从这本词典中获得对象?

回答

18

添加新initWithDictionary:方法Order

- (instancetype)initWithDictionary:(NSDictionary*)dictionary { 
    if (self = [super init]) { 
     self.OrderId = dictionary[@"OrderId"]; 
     self.Title = dictionary[@"Title"]; 
     self.Weight = dictionary[@"Weight"];  
    } 
    return self;  
} 

不要忘记initWithDictionary的签名添加到Order.h文件

在该方法中,你得到JSON:

NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; 
NSError *e; 
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:&e]; 
Order *order = [[Order alloc] initWithDictionary:dict]; 
+1

如果你有多大的对象,必须由一个执行initWithDictionay一个......有一些更灵活的解决方案,例如:: HTTPS://github.com/Infusion-apps/IAModelBase – ingaham

+0

另请参阅https://github.com/oarrabi/IAModelBase/issues这个问题,但我们可以管理它。雅这是好的。如有任何疑问,请与我联系。 –

11

如果对象上的属性名称与JSON字符串中的键匹配,则可以执行以下操作:

要将JSON字符串映射到对象,需要先将字符串转换为NSDictionary,然后才能在NSObject上使用Key-Value编码设置每个属性的方法。

NSError *error = nil; 
NSData *jsonData = ...; // e.g. [myJSONString dataUsingEncoding:NSUTF8Encoding]; 
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingOptionsAllowFragments error:&error]; 

MyObject *object = [[MyObject alloc] init]; 
[object setValuesForKeysWithDictionary:jsonDictionary]; 

如果键不匹配,您可以覆盖对象类中NSObject -[NSObject valueForUndefinedKey:]的实例方法。

要将您的对象映射到JSON,您可以使用Objective-C运行时自动执行此操作。与任何NSObject的子类中的以下工作:

#import <objc/runtime.h> 

- (NSDictionary *)dictionaryValue 
{ 
    NSMutableArray *propertyKeys = [NSMutableArray array]; 
    Class currentClass = self.class; 

    while ([currentClass superclass]) { // avoid printing NSObject's attributes 
     unsigned int outCount, i; 
     objc_property_t *properties = class_copyPropertyList(currentClass, &outCount); 
     for (i = 0; i < outCount; i++) { 
      objc_property_t property = properties[i]; 
      const char *propName = property_getName(property); 
      if (propName) { 
       NSString *propertyName = [NSString stringWithUTF8String:propName]; 
       [propertyKeys addObject:propertyName]; 
      } 
     } 
     free(properties); 
     currentClass = [currentClass superclass]; 
    } 

    return [self dictionaryWithValuesForKeys:propertyKeys]; 
} 
0

做到这一点的最佳方法是使用一个库序列化/反序列化 许多图书馆也有,但我喜欢的是 JagPropertyConverter https://github.com/jagill/JAGPropertyConverter

它可以将您的自定义对象转换为NSDictionary,反之亦然
即使它支持将字典或数组或任何自定义对象转换为对象(即构图)

JAGPropertyConverter *converter = [[JAGPropertyConverter alloc]init]; 
converter.classesToConvert = [NSSet setWithObjects:[Order class], nil]; 

@interface Order : NSObject 

@property (nonatomic, retain) NSString *OrderId; 
@property (nonatomic, retain) NSString *Title; 
@property (nonatomic, retain) NSString *Weight; 
@end 



//For Dictionary to Object (AS IN YOUR CASE) 

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 
[dictionary setValue:self.OrderId forKey:@"OrderId"]; 
[dictionary setValue:self.Title forKey:@"Title"]; 
[dictionary setValue:self.Weight forKey:@"Weight"]; 

Order *order = [[Order alloc]init]; 
[converter setPropertiesOf:order fromDictionary:dictionary]; 


//For Object to Dictionary 

Order *order = [[Order alloc]init]; 
order.OrderId = @"10"; 
order.Title = @"Title; 
order.Weight = @"Weight"; 

NSDictionary *dictPerson = [converter convertToDictionary:person]; 
4

假设你的属性名称和字典密钥是相同的,您可以使用此功能将任何物体

- (void) setObject:(id) object ValuesFromDictionary:(NSDictionary *) dictionary 
{ 
    for (NSString *fieldName in dictionary) { 
     [object setValue:[dictionary objectForKey:fieldName] forKey:fieldName]; 
    } 
} 
+1

这会崩溃,如果有任何字段丢失 –

+0

这应该有所帮助。在设置值之前检查fieldName的对象。 if([object respondsToSelector:NSSelectorFromString(fieldName)]) {object_setValue:[dictionary objectForKey:fieldName] forKey:fieldName]; } } } –

+0

它对我很好。谢谢! –

3

这将是更方便您:

- (instancetype)initWithDictionary:(NSDictionary*)dictionary { 
     if (self = [super init]) { 
      [self setValuesForKeysWithDictionary:dictionary];} 
     return self; 
    } 
0

定义你的自定义类继承自“AutoBindObject”。声明与NSDictionary中的键名称相同的属性。然后调用方法:

[customObject loadFromDictionary:dic]; 

其实,我们可以自定义映射类不同的属性名称在字典键。除此之外,我们可以绑定嵌套对象。
请看看这个演示。用法很简单:
https://github.com/caohuuloc/AutoBindObject

相关问题