【问题标题】:iPhone RestKit how to load a local JSON file and map it to a core data entity?iPhone RestKit 如何加载本地 JSON 文件并将其映射到核心数据实体?
【发布时间】:2012-05-05 12:57:16
【问题描述】:

我正在构建一个双向保管箱同步应用程序。我从核心数据加载对象,将它们转换为 JSON 并将它们发送到保管箱。但是,当我进行同步时,我会将一组本地 JSON 文件与保管箱 JSON 文件进行比较。如果检测到冲突,则应用同步逻辑。 由于同步逻辑,可能会下载远程 JSON 文件并将替换本地 JSON 文件。

所以我最终在本地文档目录中得到了一堆 JSON 文件。

如何使用 RestKit 使用我定义的映射将本地 JSON 文件反序列化回对象? RKTwitterCoreData 从基于 Web 的 JSON 创建核心数据实体。我正在尝试对本地 JSON 文件执行相同的操作。

有一堆 loadObjects 方法,但它们似乎都适用于网络调用:

- (RKObjectLoader*)loadObjectsAtResourcePath:(NSString*)resourcePath delegate:(id<RKObjectLoaderDelegate>)delegate;

谢谢!

【问题讨论】:

  • 您是否尝试将本地路径传递给 loadObjectsAtResourcePath 方法?

标签: iphone objective-c ios json restkit


【解决方案1】:

这是来自 Rest-Kit 文档,还没有尝试过,但看起来像是开始,因为他们使用 JSON 字符串。

您可以在这里找到它: look at the bottom of the page

NSString* JSONString = @"{ \"name\": \"The name\", \"number\": 12345}";
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) {
    // Parser error...
}


RKObjectMappingProvider* mappingProvider = [RKObjectManager sharedManager].mappingProvider;
RKObjectMapper* mapper = [RKObjectMapper mapperWithObject:parsedData mappingProvider:mappingProvider];
RKObjectMappingResult* result = [mapper performMapping];
if (result) {
    // Yay! Mapping finished successfully
}

编辑 请参阅关于保存上下文的 rob5408 说明:

 [[RKObjectManager sharedManager].objectStore.managedObjectContext save:&error];

【讨论】:

  • 感谢@shannoga,这非常有帮助。我想指出,我必须在之后保存 Core Data 上下文才能使对象持久存在。 [[RKObjectManager sharedManager].objectStore.managedObjectContext save:&error];
【解决方案2】:

如果你想拥有与“默认”Restkit 函数 - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects 完全相同的行为 你可以用它来获得宝贵的objects NSArray:

RKObjectMappingResult* result = [mapper performMapping];
NSArray* objects = [result asCollection];

【讨论】:

    【解决方案3】:

    这是我用于将 Core Data 转换为 JSON 到 Core Data 的方法。

      -(void)deserializeFileAtPath:(NSString*)filePath
    {
        DLog(@"Deserialize file: %@",filePath);
        NSError* error = nil;
        NSString *stringJSON = [NSString stringWithContentsOfFile:filePath usedEncoding:nil error:&error];
        if(error)
        {
            NSLog(@"Error reading from file: %@", filePath);
        }
    
        //restore the dictionary, as it was serialized
        NSDictionary* serializationDictionary =  [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:filePath] options:NSJSONReadingMutableContainers error:&error];
    
        //Here you must ensure that your object mapping exists
        [CoreDataWrapper setupCoreDataObjectMapping];
    
    //top level object within JSON it will have one entity that you really want to deserialize. Without a wrapper, the mapper would not know what the top level entity really is
        CoreDataWrapper* wrapper = [CoreDataWrapper object];
    
        RKObjectMapper* mapper;
        error = nil;
    
    //this performs deserialization. if you get errors about designated initializer not being called, you have setup a wrong object mapping. You need to define RKManagedObjectMapping for your core data classes
        mapper = [RKObjectMapper mapperWithObject:serializationDictionary 
                                  mappingProvider:[RKObjectManager sharedManager].mappingProvider];
        RKObjectMappingResult* result = [mapper performMapping];
    
        //top level object within wrapper that holds the real payload
        RealCoreDataEntity* realCoreData = [result asObject];
        realCoreData.wrapper = wrapper;
    
    //just in case
        [[wrapper managedObjectContext]save:nil];
    
    //prints what we got back
        DLog(@"%@", realCoreData);
    
    //prints any nested relationships
        for(NestedRelationshipObject* relationshipEntity in realCoreData.relationship)
        {
            DLog(@"Nested entity:%@", relationshipEntity);
        }
    
    }
    

    以下是定义嵌套 RestKit 对象模型的方法。在反序列化这种结构的 JSON 文件时,它会自动为您创建所有嵌套关系,甚至合并托管对象上下文!

    +(void)setupCoreDataObjectMapping
    {
    
    RKObjectManager *objectManager = [RKObjectManager sharedManager ] ;
    
    // Setup our object mappings    
    /*!
     Mapping by entity. Here we are configuring a mapping by targetting a Core Data entity with a specific
     name. This allows us to map back Twitter user objects directly onto NSManagedObject instances --
     there is no backing model class!
     */
    //********************************    
    RKManagedObjectMapping* nestedRelationshipMapping = [RKManagedObjectMapping mappingForEntityWithName:@"NestedRelationshipObject"];
    //UUID determines which objects get updated and which ones get created during the mapping process
    nestedRelationshipMapping.primaryKeyAttribute = @"uuid";
    [nestedRelationshipMapping mapKeyPathsToAttributes:
     @"IKeepTheseTheSame", @"IKeepTheseTheSame",
     @"AnotherValue",@"AnotherValue",
     //keep adding your attributes
     nil];
    [objectManager.mappingProvider addObjectMapping:nestedRelationshipMapping];
    
    
    
    
    //********************************    
    
    RKManagedObjectMapping* mainPayloadMapping = [RKManagedObjectMapping mappingForEntityWithName:@"RealCoreDataEntity"];
    mainPayloadMapping.primaryKeyAttribute = @"uuid";
    [mainPayloadMapping mapKeyPathsToAttributes:
     @"companyName",@"companyName",
     //keep adding your attributes
     nil];
    
    
    //this is the main payload. I create all of it's relationships before, and then add them to the mapping.
    [mainPayloadMapping mapRelationship:@"relationshipName" withMapping:nestedRelationshipMapping];
    [objectManager.mappingProvider addObjectMapping:mainPayloadMapping];
    
    
    [objectManager.mappingProvider setSerializationMapping:[mainPayloadMapping inverseMapping] forClass:[YourNSManagedObjectSubclass class]];
    
    
    [objectManager.mappingProvider setMapping:nestedRelationshipMapping forKeyPath:@"mainPayloadToNestedDataRelationshipName"];
    [objectManager.mappingProvider setMapping:mainPayloadMapping forKeyPath:@"wrapperToMainPayloadRelationshipName"];
    
    
    //this is a top level JSON object. It's name will not be identified within the object, but it's relationshipName will be. The result of deserializing this object would be an object that is being wrapped.
    RKManagedObjectMapping* wrapperMapping = [RKManagedObjectMapping mappingForClass:[IconFileWrapper class]];
    iconWrapperMapping.primaryKeyAttribute = @"uuid";
    //    keyPath and attribute names. must be even
    [iconWrapperMapping mapKeyPathsToAttributes:@"uuid",@"uuid",nil];
    //keep adding your attributes
    [iconWrapperMapping mapRelationship:@"relationshipName" withMapping:mainPayloadMapping];
    
    [objectManager.mappingProvider addObjectMapping:wrapperMapping];
    [objectManager.mappingProvider setSerializationMapping:[wrapperMapping inverseMapping] forClass:[YourWrapperNSManagedObjectSubclass class]];
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-03
      • 2013-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      相关资源
      最近更新 更多