RestKit:为外键关系创build存根
我正在努力映射我的JSON API与RestKit返回的外键关系。
具体来说,我使用Loopback来生成一个API,像Team
和User
这样的实体。 有两个terminal默认情况下返回以下JSON:
/团队/
[ { "title": "Team Title", "id": 1, } ]
/用户/
[ { "name": "Alice", "id": 1, "teamId": 1, }, { "name": "Bob", "id": 2, "teamId": 1, }, ... ]
现在这是一个非常简单的API,对吧? 使用RestKit进行映射应该很容易,但是即使在阅读所有关于该主题的其他问题之后(例如, 寻求有关浅层路由的最佳RestKit / CoreData映射和JSON结构的build议,使用RestKit的 外键关系映射 , Restkit:GET远程链接对象当外键指的是在核心数据中缺less本地对象 ),我只是不知道如何将整个对象图加载到核心数据。
如果它使事情变得简单,我当然也可以改变API。 出于显而易见的原因,我不希望在每个User
embedded整个Team
对象,而是使用外键代替。 此外,我想保持端点分开,主要是因为这是Loopback默认生成API的方式。
所以我试着用下面的映射来调用两个Endpoints(按照一个不重要的顺序):
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)]];
正如其他问题(如上面链接的那样)中所build议的,我使用RKConnectionDescription
通过瞬态teamId
属性build立关系。 映射可以正常工作,JSON有效负载包括Team
和User
对象作为数组(在响应描述符中使用keyPath而不是pathPattern),但失败时会使用单独的端点进行调用,而这些端点彼此独立地调用。 在这种情况下,连接关系引用的对象可能尚未创build。 所以为了解决这个问题,应该创build一个Stub对象 ,只有在这种情况下填充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)]];
当我打开跟踪日志logging,但我没有看到这个映射执行,但。 我究竟做错了什么? 这个映射是否被跳过,因为还有一个已经匹配相同的模式? 当我注释掉User
映射时,它完成了它的工作。
编辑3:所以RestKit实际上只使用最后一个响应描述符添加到那些匹配给定的path和相同的键path的对象pipe理器, 这里讨论的GitHub 。 感谢下面的答案,使用nil
键path映射解决了这个问题:
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)]];
我以为我的下面的答案以前的工作,但也许我总是在关于响应描述符完全匹配的评论中偷偷摸摸的问题。
因此,创build另一个映射,但将其设置为无keypath映射,并在@"teamId"
的响应描述符上使用@"teamId"
。 这将导致RestKit从响应中提取一个组ID的数组,并将它们作为对象项处理,并分离到用户对象。
JSON很好。 只要创build一个新的响应描述符,它使用了一个teamStubMapping
,这是一个像teamMapping
这样的新映射,但是用id
replace了id
。 这个响应描述符的path模式应该是@"Users"
。