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

Iphone 通过RestKit将JSON的本地NSString反序列化为对象(无网络下载),iphone,ios,restkit,Iphone,Ios,Restkit,是否可以通过RestKit将JSON的NSString反序列化为对象?我检查了API列表,没有找到可以用于此目的的东西。我能找到的最接近的是在解析输入后返回NSDictionary的各种解析器类。我假设RestKit在下载响应后使用这些解析器,所以我的想法是,该功能在RestKit中的某个地方可用,但不会公开 如果我没有遗漏任何东西,并且这个功能没有公开,那么还有什么替代方案呢?两个明显的问题看起来不太有希望:获取结果的NSDictionary,然后尝试自己反序列化(有效地重新实现RestKit

是否可以通过RestKit将JSON的
NSString
反序列化为对象?我检查了API列表,没有找到可以用于此目的的东西。我能找到的最接近的是在解析输入后返回
NSDictionary
的各种解析器类。我假设RestKit在下载响应后使用这些解析器,所以我的想法是,该功能在RestKit中的某个地方可用,但不会公开

如果我没有遗漏任何东西,并且这个功能没有公开,那么还有什么替代方案呢?两个明显的问题看起来不太有希望:获取结果的
NSDictionary
,然后尝试自己反序列化(有效地重新实现RestKit),或者尝试深入RestKit源代码,看看这是否会以某种方式暴露出来(看起来很乏味且容易出错)

提前感谢您的帮助


PS:其思想是,反序列化对象上的字符串属性实际上是另一组对象(某种意义上是嵌入式JSON)的JSON表示,它在运行时根据需要反序列化

这不是你要找的吗

从没有任何答案的视图来看,RestKit中似乎还不存在此功能。我没有花更多的时间试图弄清楚如何进行映射,而是使用JsonKit解析器的输出编写了自己的映射程序,并删除了对RestKit的依赖(将内置类用于网络活动)。现在,我的映射器不是通用的(它对对象的布局和json中对象的名称有一些依赖关系),但它用于项目目的。稍后我可能会回来,并将其转换为更通用的对象映射库

编辑:选择此答案是因为截至此答案的日期(2012年1月21日)没有其他答案。从那时起,我停止了对iOS的研究,再也没有访问过这个问题。现在我选择Ludovic的答案是因为另一位用户的评论和对该答案的投票。

非常“简单”:


一个更加面向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);
}
NSString*JSONString=JSONString;
NSString*MIMEType=@“应用程序/json”;
n错误*错误=nil;
id parser=[[RKParserRegistry sharedRegistry]parserFormetype:MIMEType];
id parsedData=[parser objectFromString:JSONString error:&error];
if(parsedData==nil&&error){
NSLog(@“ERROR:JSON解析错误”);
}
RKObjectMappingProvider*mappingProvider=[RKObjectManager sharedManager].mappingProvider;
RKObjectMapper*mapper=[RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider];
RKObjectMappingResult*结果=[mapper performMapping];
如果(结果){
NSArray*resultArray=result.asCollection;
MyObject*object=[resultArray lastObject];
NSLog(@“我的对象:%@”,对象);
}


这适用于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]);
}

这适用于RESTKit0.20,使用核心数据实体。它基于@innerself给出的解决方案

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]
}

对于Restkit 0.22,可以使用以下代码。这将返回一个RKMappingResult,您可以在其中使用property.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;
}

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

此操作分为三个阶段

第一个是将JSON字符串解析为NSDictionary、NSArray等。这是最简单的部分

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:^{
记住用您自己的映射替换此词典。键
[NSNull]
从根映射此对象

    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;
}];
现在需要运行已放入我们创建的operationQueue中的任务。正是在这一阶段,与现有NSManagedObject建立了连接

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

我知道这些解析器类。它们将字符串解析为
NSDictionary
,这是整个反序列化过程的第一部分。我需要的功能,需要一个字符串和输出映射的对象。换句话说,在RestKit按顺序完成的三件事(下载响应、解析下载的字符串、映射对象)中,我只需要完成最后两件事。我有一些JSON需要映射到我的模型(NSManagedObject)。你找到解决办法了吗?@MikeBevz:我自己写了地图。:-)我写了更多的细节来回答这个问题。为什么这是选择的答案?卢多维奇的解决方案非常有效@凯尔:之所以选择这个答案,是因为截至这个答案的日期(2012年1月21日),没有其他答案。从那时起,我停止了对iOS的研究,再也没有访问过这个问题。尽管我目前无法亲自验证答案,但我选择Ludovic的答案是因为您的评论。您是否知道如何从已配置的RKObjectManager中执行此操作?这就是您所寻找的吗+1.我的实现的关键是您的最后一步,operationQueue.WaitUntilalAllOperationsDefished()。否则,映射过程会在完成映射所需关系之前返回我的NSManagedObject。这对我来说很有用。如何让RestKit将对象存储回核心数据?我尝试了[[RKObjectManager sharedManager].managedObjectStore.persistentStoreManagedObjectContext saveToPersistentStore:&错误];mappingResult=mapper.mappingResult之后;但那没用。建议?
    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;
}];
if ([operationQueue operationCount]) {
    [operationQueue waitUntilAllOperationsAreFinished];
}