【发布时间】:2014-07-11 15:46:32
【问题描述】:
我正在努力将我的 JSON API 返回的外键关系与 RestKit 进行映射。
具体来说,我使用Loopback 来生成带有Team 和User 等实体的API。默认情况下有两个 Endpoints 返回以下 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。出于显而易见的原因,我不想在每个 User 中嵌入整个 Team 对象,而是使用外键。另外,我想保持端点分开,主要是因为这是 Loopback 默认生成 API 的方式。
所以我尝试使用以下映射调用两个端点(按不重要的顺序):
Team映射
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)]];
User映射
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 属性建立关系。该映射适用于包含 Team 和 User 对象作为数组的 JSON 有效负载(在响应描述符中使用 keyPath 而不是 pathPattern),但由于我相互独立调用的单独端点而失败。在这种情况下,连接关系所引用的对象可能尚未创建。因此,为了解决这个问题,应该创建一个 存根对象,并在这种情况下只填充 id 属性。
如何使用 RestKit 映射来实现这一点?
编辑:如果我将 JSON 结构从 "teamId": 1 更改为 "team": { "id": 1 } 并使用 keyPath team 添加另一个响应描述符会有所帮助吗?不确定环回是否容易做到这一点。
最好的方法是什么?
编辑 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)]];
但是,当我打开跟踪日志记录时,我看不到此映射已执行。我究竟做错了什么?是否跳过了这个映射,因为已经有另一个匹配相同的模式?当我注释掉 User 映射时,它就完成了它的工作。
编辑 3: 所以 RestKit 确实实际上只使用添加到对象管理器的最后一个响应描述符,这些描述符与给定路径匹配并且具有相同的键路径,正如所讨论的 @ 987654325@。感谢下面的答案,使用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)]];
【问题讨论】:
标签: ios core-data foreign-keys restkit restkit-0.20