使用 Restkit 从 JSON 数组映射关系

Mapping relationships from JSON array with Restkit

我会尽量描述这个问题...

场景

假设我有一个 NSManagedObject 'User'

@class Premise;

@interface User : NSManagedObject

@property (nonatomic, retain) NSNumber * identifier;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *premises;
@end

@interface User (CoreDataGeneratedAccessors)

- (void)addPremisesObject:(Premise *)value;
- (void)removePremisesObject:(Premise *)value;
- (void)addPremises:(NSSet *)values;
- (void)removePremises:(NSSet *)values;

@end

我还有一个 NSManagedObject 'Premise'

@class User;

@interface Premise : NSManagedObject

@property (nonatomic, retain) NSNumber * identifier;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) User *user;

@end

基于它,我正在创建关系路由以将 'Premise' 的 JSON 数组映射到 'User' 对象上的 'premises' 属性。

路线如下:

 let getPremisesRoute = RKRoute(relationshipName: "premises", 
                                objectClass: User.self, 
                                pathPattern: "user/:identifier/premises", 
                                method: .GET)

这是 JSON 响应 (/user/1/premises):

[
    {
        "id": 35,
        "name": "Icaraí"
    },
    {
        "id": 32,
        "name": "Remanso"
    }
]

这是响应描述符:

  let getPremisesResponseDescriptor = RKResponseDescriptor(mapping: premiseMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful))

这里是'User'和'Premise'

各自的映射
let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc)
userMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])      
userMapping.identificationAttributes = ["identifier"]
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping))


let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])
premiseMapping.identificationAttributes = ["identifier"]

现在我的问题

显然,Restkit 在映射过程中有点混乱。这是请求后的数据库:

用户Table:

前提Table:

请注意,实体之间并未创建关系。

现在,如果我将响应描述符的映射从 premise 更改为 user 映射,数据库将更改为:

用户Table:

前提Table:

我真的很困惑发生了什么,我尝试了很多解决方案都没有成功。

JSON 响应是否异常或我做错了什么? JSON 响应似乎是一种常见的模式,没有关键路径。

您未正确处理映射,或者至少您的映射对于您正在做的事情是错误的。考虑响应是一个用户,但只是一个用户的前提,而不是像现在这样将其视为一个简单的前提列表。然后映射到用户并插入场所。类似于:

RKResponseDescriptor(mapping: userMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful))

这里是'User'和'Premise'

各自的映射
let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc)
userMapping.addAttributeMappingsFromDictionary(["@metadata.routing.parameters.idEntities":"identifier"])      
userMapping.identificationAttributes = ["identifier"]
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping))


let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])
premiseMapping.identificationAttributes = ["identifier"]

你在响应中没有用户名所以你不能映射它,而用户id实际上在请求中所以你需要使用元数据来提取它。

好的,我找到了一个基于@Wain 使用外键的解决方案的可能解决方案。

我向 'Premise' 实体添加了一个新的 属性 'userID' 并使用元数据

将其映射到 URL 上的标识符
let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc)

 premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name", "@metadata.routing.parameters.identifier":"userID"])

然后我在'premiseMapping'

中添加了关系连接
premiseMapping.addConnectionForRelationship("user", connectedBy: ["userID":"identifier"])

如果谁有更优雅的解决方案,请与我们分享。