Deserializing local NSString of JSON into objects via RestKit (no network download)

前端 未结 9 1124
悲&欢浪女
悲&欢浪女 2020-12-14 20:49

Is it possible to deserialize an NSString of JSON into objects via RestKit? I checked the API list here and could not find something that would serve for this p

相关标签:
9条回答
  • 2020-12-14 21:14

    This works for Restkit 0.20, using Core Data Entities. It is based in the solution given by @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]
    }
    
    0 讨论(0)
  • 2020-12-14 21:19

    Judging by the views without any answers, it seems this facility does not exist in RestKit yet. Instead of spending more time trying to figure out how to do the mapping, I wrote my own mapper using the output of JsonKit parser and removed the dependency on RestKit (used the builtin classes for network activity). Right now my mapper is not generic (it has a few dependencies on how the objects are laid out and their names in json) but it works for the purposes of the project. I might come back later and turn it into a more generic object mapping library later on.

    EDIT: This was selected answer because there was no other answer as of this answer's date (Jan 21, 2012). Since then, I stopped working on iOS and never visited this question again. Now I am selecting Ludovic's answer because of another user's comment and the upvotes for that answer.

    0 讨论(0)
  • 2020-12-14 21:21

    You can see how RestKit does this internally in the RKManagedObjectResponseMapperOperation class.

    There are three stages of this operation.

    The first is to parse the JSON string into NSDictionarys, NSArrays, etc. This is the easiest part.

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

    Next you need to run a mapping operation to convert this data into your NSManagedObjects. This is a bit more involved.

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

    Remember to replace this dictionary with your own mappings. The key [NSNull null] maps this object from the root.

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

    You now need to run the tasks that have been put into the operationQueue we created. It is at this stage that connections to existing NSManagedObjects are made.

    if ([operationQueue operationCount]) {
        [operationQueue waitUntilAllOperationsAreFinished];
    }
    
    0 讨论(0)
提交回复
热议问题