通过RestKit将JSON的本地NSString反序列化为对象(无networking下载)

是否有可能通过RestKit反序列化JSON的NSString成对象? 我在这里检查了API列表,找不到可用于此目的的东西。 我能find的最接近的是parsinginput后返回NSDictionary的各种parsing器类。 我假设RestKit在下载响应之后使用这些parsing器,所以我认为这个function在RestKit中可用,但不公开公开。

如果我没有遗漏任何东西,而且这个function没有暴露出来,还有什么替代方法呢? 两个明显的看起来不太有希望:得到结果的NSDictionary并尝试反序列化自己(有效地重新实现RestKit)或尝试潜入RestKit源,看看是否可以以某种方式暴露(看起来乏味和容易出错)。

在此先感谢您的帮助。

PS:这个想法是反序列化的对象上的string属性实际上是另一组对象的JSON表示(从某种意义上说是embedded式JSON),并且在运行时按需进行反序列化。

漂亮“简单”:

 NSString *stringJSON; ... RKJSONParserJSONKit *parser; NSError *error= nil; parser= [[[RKJSONParserJSONKit alloc] init] autorelease]; MyManagedObject *target; target= [MyManagedObject object]; NSDictionary *objectAsDictionary; RKObjectMapper* mapper; objectAsDictionary= [parser objectFromString:stringJSON error:&error]; mapper = [RKObjectMapper mapperWithObject:objectAsDictionary mappingProvider:[RKObjectManager sharedManager].mappingProvider]; mapper.targetObject = target; RKObjectMappingResult* result = [mapper performMapping]; NSLog(@"%@", [result asObject]); 

截至RestKit 0.20.0-pre2

 NSString* JSONString = @"{ \"name\": \"The name\", \"number\": 12345}"; NSString* MIMEType = @"application/json"; NSError* error; NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding]; id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:MIMEType error:&error]; if (parsedData == nil && error) { // Parser error... } AppUser *appUser = [[AppUser alloc] init]; NSDictionary *mappingsDictionary = @{ @"someKeyPath": someMapping }; RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary]; mapper.targetObject = appUser; NSError *mappingError = nil; BOOL isMapped = [mapper execute:&mappingError]; if (isMapped && !mappingError) { // Yay! Mapping finished successfully NSLog(@"mapper: %@", [mapper representation]); NSLog(@"firstname is %@", appUser.firstName); } 

这适用于Restkit 0.21.0:

 NSString* jsonFilePath = [[NSBundle mainBundle] pathForResource:@"fileName" ofType:@"json"]; NSString* JSONString = [NSString stringWithContentsOfFile:jsonFilePath encoding:NSUTF8StringEncoding error:NULL]; NSError* error; NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding]; id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error]; if (parsedData == nil && error) { // Parser error... } //_objectManager is RKObjectManager instance NSMutableDictionary *mappingsDictionary = [[NSMutableDictionary alloc] init]; for (RKResponseDescriptor *descriptor in _objectManager.responseDescriptors) { [mappingsDictionary setObject:descriptor.mapping forKey:descriptor.keyPath]; } RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary]; NSError *mappingError = nil; BOOL isMapped = [mapper execute:&mappingError]; if (isMapped && !mappingError) { NSLog(@"result %@",[mapper mappingResult]); } 

这适用于Restkit 0.20,使用核心数据实体 。 它基于@innerself给出的解决scheme

 NSString* jsonFilePath = [[NSBundle mainBundle] pathForResource:@"info-base" ofType:@"json"]; NSString* JSONString = [NSString stringWithContentsOfFile:jsonFilePath encoding:NSUTF8StringEncoding error:NULL]; NSError *error = nil; NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding]; id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error]; if (parsedData == nil && error) { // Parser error... NSLog(@"parse error"); } //_objectManager is RKObjectManager instance NSMutableDictionary *mappingsDictionary = [[NSMutableDictionary alloc] init]; for (RKResponseDescriptor *descriptor in [RKObjectManager sharedManager].responseDescriptors) { [mappingsDictionary setObject:descriptor.mapping forKey:descriptor.keyPath]; } RKManagedObjectMappingOperationDataSource *datasource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext cache:[RKManagedObjectStore defaultStore].managedObjectCache]; RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary]; [mapper setMappingOperationDataSource:datasource]; NSError *mappingError = nil; BOOL isMapped = [mapper execute:&mappingError]; if (isMapped && !mappingError) { // data is in [mapper mappingResult] } 

您可以在RKManagedObjectResponseMapperOperation类中看到RestKit如何在内部执行此RKManagedObjectResponseMapperOperation

这个操作有三个阶段。

首先是将JSONstringparsing为NSDictionarys,NSArrays等,这是最简单的部分。

 id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:error]; 

接下来,您需要运行映射操作将这些数据转换为您的NSManagedObjects。 这是多一点涉及。

 __block NSError *blockError = nil; __block RKMappingResult *mappingResult = nil; NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; operationQueue.maxConcurrentOperationCount = 1; [[RKObjectManager sharedManager].managedObjectStore.persistentStoreManagedObjectContext performBlockAndWait:^{ 

记住用自己的映射来replace这个字典。 关键[NSNull null]映射来自根的这个对象。

  NSDictionary *mappings = @{[NSNull null]: [jotOfflineRequestStatus mapping]}; RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappings]; RKManagedObjectMappingOperationDataSource *dataSource = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:[RKManagedObjectStore defaultStore].persistentStoreManagedObjectContext cache:[RKManagedObjectStore defaultStore].managedObjectCache]; dataSource.operationQueue = operationQueue; dataSource.parentOperation = mapper; mapper.mappingOperationDataSource = dataSource; [mapper start]; blockError = mapper.error; mappingResult = mapper.mappingResult; }]; 

您现在需要运行已经放入我们创build的operationQueue中的任务。 正是在这个阶段,连接到现有的NSManagedObjects被做。

 if ([operationQueue operationCount]) { [operationQueue waitUntilAllOperationsAreFinished]; } 

更多iOS 5+面向的答案:

 NSString* JSONString = jsonString; NSString* MIMEType = @"application/json"; NSError* error = nil; id<RKParser> parser = [[RKParserRegistry sharedRegistry] parserForMIMEType:MIMEType]; id parsedData = [parser objectFromString:JSONString error:&error]; if (parsedData == nil && error) { NSLog(@"ERROR: JSON parsing error"); } RKObjectMappingProvider* mappingProvider = [RKObjectManager sharedManager].mappingProvider; RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider]; RKObjectMappingResult* result = [mapper performMapping]; if (result) { NSArray *resultArray = result.asCollection; MyObject *object = [resultArray lastObject]; NSLog(@"My Object: %@", object); } 

对于Restkit 0.22,您可以使用此代码。 这将返回一个RKMappingResult,其中您可以使用属性.array映射后枚举对象。

 - (RKMappingResult *)mapJSONStringWithString:(NSString *)jsonString { RKMappingResult *result = nil; NSError* error; NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; id parsedData = [RKMIMETypeSerialization objectFromData:data MIMEType:RKMIMETypeJSON error:&error]; if (parsedData == nil && error) { NSLog(@"json mapping error"); } NSDictionary *mappingsDictionary = @{@"":[CustomMappingClass getMappingForUsers]}; ObjectClass *obj = [ObjectClass new]; RKMapperOperation *mapper = [[RKMapperOperation alloc] initWithRepresentation:parsedData mappingsDictionary:mappingsDictionary]; NSError *mappingError = nil; mapper.targetObject = obj; BOOL isMapped = [mapper execute:&mappingError]; if (isMapped && !mappingError) { result = [mapper mappingResult]; } return result; } 

根据没有任何答案的意见来看,这个设施似乎还不存在于RestKit中。 我没有花费更多的时间来弄清楚如何完成映射,而是使用JsonKitparsing器的输出编写了我自己的映射器,并删除了RestKit的依赖(使用内置类进行networking活动)。 现在我的映射器不是通用的(它对json中对象的布局和名称有一些依赖关系),但是它适用于项目。 稍后我可能会回来,并在以后把它变成一个更通用的对象映射库。

编辑:这是select的答案,因为没有其他答案作为这个答案的date(2012年1月21日)。 从那时起,我停止在iOS上工作,从来没有再次访问这个问题。 现在我正在selectLudovic的答案,因为另一个用户的评论和upvotes答案。