使用 RestKIt 在核心数据实体中映射 json 对象

Posted

技术标签:

【中文标题】使用 RestKIt 在核心数据实体中映射 json 对象【英文标题】:Mapping json object on coredata entity using RestKIt 【发布时间】:2014-02-03 08:28:17 【问题描述】:

我正在使用 RestKit 开发一些待办事项列表应用程序。我在ios中使用CoreData返回的json表单服务器面临一些映射问题。

情景

以下是我正在使用的列表和任务实体的图像。

当有人向服务器上的列表添加新任务时,我返回该特定列表的以下 Json:

`GET www.mydomain.com\api\list\1`

        [  "list" : 

           "listID" : "1",
            "listName" : "New List ",
            "listSyncStatus" : "1"
          ,
        "tasks" : [  "listID" : "1",
              "taskCompletionStatus" : "1",
              "taskID" : "24",
              "taskName" : "Server Added 2",
              "taskSyncStatus" : "1"
            ,
             "listID" : "1",
              "taskCompletionStatus" : "1",
              "taskID" : "25",
              "taskName" : "Server Added 3",
              "taskSyncStatus" : "1"
            ,
             "listID" : "1",
              "taskCompletionStatus" : "1",
              "taskID" : "23",
              "taskName" : "Server Added",
              "taskSyncStatus" : "1"
            
          ]
       
    ]

我对上述 json 的响应描述符如下:

    RKResponseDescriptor *taskResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:taskEntityMapping
                                                                                            method:RKRequestMethodGET
                                                                                       pathPattern:@"/api/list/:id"
                                                                                           keyPath:@"tasks"
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

对于我的核心数据映射,我使用以下关系映射:

    [taskEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"list"
                                                                                  toKeyPath:@"list"
                                                                                withMapping:listEntityMapping]];

我的taskEntityMapping如下:

    NSDictionary *taskObjectMapping = @
                                    @"listID" : @"listID",
                                    @"taskID" : @"taskID",
                                    @"taskName" : @"taskName",
                                    @"taskCompletionStatus" : @"taskCompletionStatus",
                                    @"taskSyncStatus" : @"taskSyncStatus"
                                ;

RKEntityMapping *taskEntityMapping = [RKEntityMapping mappingForEntityForName:@"Task" inManagedObjectStore:managedObjectStore];
[taskEntityMapping addAttributeMappingsFromDictionary:taskObjectMapping];
taskEntityMapping.identificationAttributes = @[ @"taskID" ];

而我的listEntityMapping如下:

    //ALL LISTS RELATED REQUESTS
NSDictionary *listObjectMapping = @
                                      @"listID" : @"listID",
                                      @"listName" : @"listName",
                                      @"listSyncStatus" : @"listSyncStatus",

                                  ;

RKEntityMapping *listEntityMapping = [RKEntityMapping mappingForEntityForName:@"List" inManagedObjectStore:managedObjectStore];
[listEntityMapping addAttributeMappingsFromDictionary:listObjectMapping];

listEntityMapping.identificationAttributes = @[ @"listID" ];

在执行时,我的应用程序崩溃并出现以下错误 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected a dictionary representation'

请求日志如下:

2014-02-03 13:17:29.789 RKGist[984:70b] T restkit.network:RKObjectRequestOperation.m:178 GET 'http://mydomain.com/api/list/1':
request.headers=
    Accept = "application/json";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    "User-Agent" = "RKGist/1.0 (iPhone Simulator; iOS 7.0.3; Scale/2.00)";

request.body=(null)
2014-02-03 13:17:30.670 RKGist[984:f03] T restkit.network:RKResponseMapperOperation.m:451 Mapping HTTP response to nil target object...
2014-02-03 13:17:30.670 RKGist[984:f03] D restkit.object_mapping:RKMapperOperation.m:377 Executing mapping operation for representation: (
        
        list =         
            listID = 1;
            listName = "New List ";
            listSyncStatus = 1;
        ;
        tasks =         (
                        
                listID = 1;
                taskCompletionStatus = 1;
                taskID = 24;
                taskName = "Server Added 2";
                taskSyncStatus = 1;
            ,
                        
                listID = 1;
                taskCompletionStatus = 1;
                taskID = 25;
                taskName = "Server Added 3";
                taskSyncStatus = 1;
            ,
                        
                listID = 1;
                taskCompletionStatus = 1;
                taskID = 23;
                taskName = "Server Added";
                taskSyncStatus = 1;
            
        );
    
)
 and targetObject: (null)
2014-02-03 13:17:30.671 RKGist[984:f03] T restkit.object_mapping:RKMapperOperation.m:320 Examining keyPath 'tasks' for mappable content...
2014-02-03 13:17:30.671 RKGist[984:f03] D restkit.object_mapping:RKMapperOperation.m:297 Found mappable collection at keyPath 'tasks': (
        (
                
            listID = 1;
            taskCompletionStatus = 1;
            taskID = 24;
            taskName = "Server Added 2";
            taskSyncStatus = 1;
        ,
                
            listID = 1;
            taskCompletionStatus = 1;
            taskID = 25;
            taskName = "Server Added 3";
            taskSyncStatus = 1;
        ,
                
            listID = 1;
            taskCompletionStatus = 1;
            taskID = 23;
            taskName = "Server Added";
            taskSyncStatus = 1;
        
    )
)

日志说在 keypath tasks 找到了可映射的集合。

谁能指导我在这里做错了什么。是我返回的 json 格式错误还是我的映射代码错误?

【问题讨论】:

【参考方案1】:

您的响应描述符使用keyPath:@"tasks"。这有效地“挖掘”了响应并忽略了tasks 部分之外的任何内容。这意味着在映射期间您无法访问list 部分。

addPropertyMapping: 与关系一起用于嵌套映射 - 这不是您所拥有的。实际上,您有 2 个单独的部分需要单独映射(因此,2 个响应描述符)以创建具有关联 ID(以及连接对象的 ID)的所有对象。然后,您需要使用外键映射来建立连接(使用RKConnectionDescription)。

要检查的一件事是返回的 JSON 是什么。看起来好像它可能是 1 个包含对象的大型数组,这没有任何意义。如果它是一个数组,那么您将需要更改整个方法。它应该是 1 个带有多个键的对象...

【讨论】:

以上是关于使用 RestKIt 在核心数据实体中映射 json 对象的主要内容,如果未能解决你的问题,请参考以下文章

RestKit 映射结果已填充,但未设置核心数据实体

如何在 RestKit 中定义不在同一个 JSON 文档中的实体之间的关系映射?

如何使用 RestKit 指定关系?

iOS RestKit 实体管理器映射对象数组

Restkit嵌套对象映射问题

列表内列表的RestKit对象映射