从JSON到NSObjects的对象映射库

我正在尝试构build一个parsing器/ objectMapper,它将为我从REST服务中使用的JSON构buildObjective C对象。

我从RestKit中得到了一些启发,让我的实体都拥有一个“解码列表”,它告诉映射器哪个JSON键与哪个对象相关联。 喜欢这个:

//ObjectEntity implementation + (NSDictionary*) mapProperties { /* localPropertiy - JSONProperty */ return @{ @"name": @"name", @"category": @"category", @"possible_scopes": @"possibleScopes", @"possible_descriptions": @"possibleDescriptions", @"key": @"keys" }; } + (NSDictionary*) mapRelations { return [NSDictionary dictionary]; } 

我这样做是因为我喜欢把这些可改变的值封装在它们引用的对象中。 尽可能less地使Mapper知道。

映射器做了这样的事情:

 + (NSArray*) parseData:(NSData*) jsonData intoObjectsOfType:(Class) objectClass { //Parser result from web service NSError *error = nil; CJSONDeserializer *deserializer = [CJSONDeserializer deserializer]; [deserializer setNullObject:nil]; NSArray *objects = [deserializer deserializeAsArray:jsonData error:&error]; NSMutableArray *result = [NSMutableArray array]; for (NSDictionary *o in objects) { id <EntityProtocol> entity = [[objectClass alloc] init]; NSDictionary *jsonKeys = objectClass.mapProperties; for (NSString *key in jsonKeys.allKeys) { NSString *objectProperty = jsonKeys[key]; NSString *value = o[key]; if (value) [entity setValue:value forKey:objectProperty]; } [result addObject:entity]; } return (NSArray*)result; } 

所以我给消息parsing器/映射器像这样:

 NSArray *objects = [ObjectParser parseData:self.responseData intoObjectsOfType:ObjectEntity.class]; 

这意味着parsing器必须知道我的根对象是什么,这是好的,因为从Web服务中检索它的对象当然有这方面的知识。

以上只适用于没有嵌套对象的JSON,我一直在尝试构buildparsing器,以便将关系也考虑在内,构build所需的对象并将它们插入到根对象中,这需要recursion并保持跑进死胡同。

我希望得到一些帮助,以便我能够如何处理这个或任何洞察力,就好像这样的事情存在于图书馆一样。 也许是使用或可能只是为了解决我有问题的部分。

先谢谢你。

为什么不为类添加映射?

 + (NSDictionary *)mapClasses { return @{ @"category": [Category class], // ... }; } 

对于非容器属性,甚至可以对属性进行运行时自省以避免冗余映射。

容器属性可以映射到特殊的包装对象:

 [OMContainer arrayWithClass:Key.class], @"keys", [OMContainer dicionaryWithKeyClass:ScopeID.class valueClass:Scope.class], @"possibleScopes", 

甚至可以dynamicselecttypes块:

 [OMDynamicType typeWithBlock:^(id obj){ if ([obj isKindOfClass:NSString.class] && [obj hasPrefix:@"foo"]) return Foo.class; else return Bar.class; }], @"foo", 

实现这个可以像这样:

 + (NSArray *)parseData:(NSData*)jsonData intoObjectsOfType:(Class)objectClass { NSArray *parsed = /* ... */ NSMutableArray *decoded = [NSMutableArray array]; for (id obj in parsed) { [decoded addObject:[self decodeRawObject:parsed intoObjectOfType:objectClass]]; } return decoded; } + (id)decodeRawObject:(NSDictionary *)dict intoObjectOfType:(Class)objectClass { // ... NSDictionary *jsonKeys = objectClass.mapProperties; NSDictionary *jsonClasses = objectClass.mapClasses; for (NSString *key in jsonKeys.allKeys) { NSString *objectProperty = jsonKeys[key]; NSString *value = dict[key]; if (value) { id klass = jsonClasses[key]; if (!klass) { [entity setValue:value forKey:objectProperty]; } else if (klass == klass.class) { [entity setValue:[self decodeRawObject:value intoObjectOfType:klass] forKey:objectProperty]; } else if (/* check for containers and blocks */) { // ... } } } // ... } 

考虑使用RestKit: http: //restkit.org

这个框架有你需要的一切 – REST和JSON抽象,对象映射,甚至核心数据支持以及大量真正有用的东西,所有这些都以可定制和优雅的方式实现。

更新:好的,在编写另一种映射方法的时候,我决定我不能再做了,并做了一个小框架。 它反省了对象的属性,并通过一些调整给你免费的漂亮的描述,isEqual / hashCode,免费NSCoding的支持,并允许生成/来自JSON映射器(确实,NSDictionary,但谁会用它的东西)。 所有的NSNull检查,JSON中缺less的字段,JSON中的新的意外字段都会被正常处理并正确报告。

如果有人想把这个分享给大众,你可以给我一些upvotes或评论。 我最终会这样做,但我可能会考虑更快地分享它。

我也尝试了同样的方法。 我的主要问题是,准确地描述types。 例如对于嵌套数组,我使用这样的东西:

 @{ @"friends" : @[[Person class]] } 

但事情变得混乱,因为我需要为不同types创造更多和更特殊的语法,我想支持。 最后,我停止了这个方法,并去了另一个解决scheme – 也因为运行时检查我需要做的是减缓转换。

现在有很多解决scheme。 我会build议看看真棒iOS网站。 我也想指出JSON类生成器 ,因为它允许你

  • 准确地描述你的types(包括date等的特殊映射器),
  • 会自动检查types(提供不匹配报告和提供的回退值),
  • 你不需要花费时间来编写重复的代码(而且生成的代码似乎总是“正常工作”)

我讨厌做广告,但是这个工具为我节省了很多工作,我投入了我的应用程序的其他function。 现在已经有一段时间了,现在世界似乎转向了Swift,但更有理由不浪费时间编写Objective-C的模型。

以下是一些转换为/形成JSON的代码示例:

 // converting MyClass <-> NSDictionary MyClass *myClass = [MyClass myClassWithDict:someJsonDictionary]; NSDictionary *jsonDict = [myClass toDict]; // converting NSDictionary <-> NSData NSDictionary *someJsonDictionary = [NSDictionary api_dictionaryWithJson:someJsonData]; NSData *jsonData = [someJsonDictionary api_toJson]; 

JSON类生成器也支持之前的注释中提到的function:

 -isEqual, -hash, -description, -copy, NSCoding/NSSecureCoding/NSKeyedArchiver 

在JSON响应中检查缺less的/附加的/ NSNull /可选的字段和错误的types,报告错误,正常地以故障恢复值失败,并且使用方法调度而不是运行时types自省(这是更快的)。

试用CSMapper,真是太神奇了! 您只需创build与该类命名相同的plists,映射一些属性,然后使用一行代码轻松地将字典映射到您的对象。 我已经在很多项目上进行了testing,发现它非常干净,性能卓越。 它使我能够灵活地轻松地在开发生命周期中响应API更改。

https://github.com/marcammann/CSMapper

我目前正在更新文档,并添加到个人的叉子项目,应该很快将被合并:)

https://github.com/AntonTheDev/CSMapper

我的build议是在NSObject上使用Motis类别。 它重量轻,执行自动validation您的对象types和使用非常简单。

在另一个问题中有一个问题: 在自定义对象中映射JSON对象

希望它是有用的。