我正在努力将我的
JSON API返回的外键关系映射到RestKit.
具体来说,我使用Loopback生成一个包含团队和用户等实体的API.默认情况下,有两个端点返回以下JSON:
/团队/
[
{
"title": "Team Title",
"id": 1,
}
]
/用户/
[
{
"name": "Alice",
"id": 1,
"teamId": 1,
},
{
"name": "Bob",
"id": 2,
"teamId": 1,
}, ...
]
现在这是一个非常简单的API,对吧?使用RestKit进行映射应该很容易,但即使在阅读了有关该主题的所有其他问题(例如Seeking recommendations for best RestKit/CoreData mapping and JSON structure for shallow routes,Foreign key relationship mapping with RestKit,Restkit: GET remote linked object when foreign key refers to missing local object in Core Data)之后,我也无法弄清楚如何将整个对象图加载到核心数据中.
如果它使事情变得更容易,我当然也可以改变API.出于显而易见的原因,我不想在每个用户中嵌入整个Team对象,而是使用外键.此外,我希望将端点保持分离,主要是因为这是Loopback默认生成API的方式.
所以我尝试使用以下映射调用两个端点(按照无关紧要的顺序):
团队映射
RKEntityMapping *teamMapping = [RKEntityMapping mappingForEntityForName:@"Team" inManagedObjectStore:objectManager.managedObjectStore];
[teamMapping addAttributeMappingsFromArray:@[ @"title", @"id" ]];
teamMapping.identificationAttributes = @[ @"id" ];
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:teamMapping method:RKRequestMethodAny pathPattern:@"Teams" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
用户映射
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:@"User" inManagedObjectStore:objectManager.managedObjectStore];
[userMapping addAttributeMappingsFromArray:@[ @"name", @"id", @"teamId" ]];
userMapping.identificationAttributes = @[ @"id" ];
[userMapping addConnectionForRelationship:@"team" connectedBy:@{ @"teamId": @"id" }];
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:userMapping method:RKRequestMethodGET pathPattern:@"Users" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
正如其他问题(如上面链接的那些)中所建议的那样,我使用RKConnectionDescription通过瞬态teamId属性建立关系.该映射适用于JSON有效负载,该有效负载包括Team和User对象作为数组(在响应描述符中使用keyPath而不是pathPattern),但是由于我彼此独立调用的单独端点失败.在这种情况下,可能尚未创建连接关系所引用的对象.因此,要解决此问题,应创建一个Stub对象,只在该情况下填充id属性.
如何使用RestKit映射实现此目的?
编辑:如果我将JSON结构从“teamId”更改为1:“team”:{“id”:1}并在keyPath团队中添加另一个响应描述符会有帮助吗?不确定Loopback是否容易.
最好的方法是什么?
编辑2:所以我添加了以下存根映射:
RKEntityMapping *teamStubMapping = [RKEntityMapping mappingForEntityForName:@"Team inManagedObjectStore:objectManager.managedObjectStore];
[teamStubMapping addAttributeMappingsFromDictionary:@{@"teamId": @"id"}];
teamStubMapping.identificationAttributes = @[ @"id" ];
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:teamStubMapping method:RKRequestMethodAny pathPattern:@"Users" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
当我打开跟踪日志记录时,我没有看到执行此映射.我究竟做错了什么?这个映射是否被跳过,因为还有另一个映射已匹配相同的模式?当我注释掉用户映射时,它就完成了它的工作.
编辑3:所以RestKit实际上只使用添加到匹配给定路径和相同密钥路径的对象管理器的最后一个响应描述符,如here on GitHub所讨论的.由于下面的答案,使用nil密钥路径映射解决了问题:
RKEntityMapping *teamStubMapping = [RKEntityMapping mappingForEntityForName:@"Team inManagedObjectStore:objectManager.managedObjectStore];
[teamStubMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"id"]];
teamStubMapping.identificationAttributes = @[ @"id" ];
[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:teamStubMapping method:RKRequestMethodAny pathPattern:@"Users" keyPath:@"teamId" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
最佳答案 我认为我的下面的答案以前有用,但也许我总是在关于响应描述符的完全匹配的评论中悄悄解决问题.
因此,创建另一个映射,但将其设为nil keypath mapping并在@“teamId”的响应描述符上使用密钥路径.这将导致RestKit从响应中提取团队ID数组,并将它们作为对象项处理,与用户对象分开.
JSON很好.只需创建一个新的响应描述符,它使用teamStubMapping,这是一个像teamMapping这样的新映射,但用teamId替换id.此响应描述符的路径模式应为@“Users”.