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