【发布时间】:2014-05-07 22:20:12
【问题描述】:
我一直在研究这个问题。以下是一些有助于在 RestKit 中映射此 JSON 响应的发现
JSON 响应对象包含三个顶级对象:
位置是一个数组
cityKey 对象
stateKey 对象
Since Restkit is written in Objective-C, I looked at it as if I were going to directing 映射这些对象并解析出数据
我编写了以下代码来映射 Location Class\Object 的 NSDictionary 部分:
RKObjectMapping* locationMapping = [RKObjectMapping mappingForClass:[Location class]];
[locationMapping addAttributeMappingsFromDictionary:@{
@"distance": @"distance",
@"major": @"major",
@"minor": @"minor" }];
我为整个 class\object , Locations 编写了以下代码: //这也应该是一个 NSDictionary
RKObjectMapping *locationsMapping = RKObjectMapping mappingforclass: [Locations class]];
This appears to be a mapping array should be a dictionary.
[locationsMapping addAttributeMappingsFromArray:@[@"locations", @"cityKey",@"stateKey"]];
我发现在对整个对象位置使用 Array 时出现错误。这将运行并从以下返回部分成功的结果:
RKResponseDescriptor *locationDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:locationMapping method:RKRequestMethodAny pathPattern:@"/location" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
[[RKObjectManager sharedManager] addResponseDescriptor:locationDescriptor];
[[RKObjectManager sharedManager] postObject:nil path:(_enterLocation) parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"It Worked: %@", [mappingResult array]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"It Failed: %@", error);
}];
This returns the successful responseJSONdata, but mappingResult dictionary returns:
2014-05-07 17:28:39.770 MyApp[163:60b] It Worked: {
locations = (
);
}
The actual JSONOBJECTWITHDATA returned as response.body is:
response.body={
"locations": [
{
"distance": 0.5,
"major": 2,
"minor": 4,
},
{
"distance": 1.0,
"major": 2,
"minor": 11,
}
],
"cityKey": "12",
"stateKey": "41"
}
从阅读中,
Will RestKit's dynamic mapping solve this complex JSON mapping?
和
Feeding parsed data to RKMapperOperation throws NSUnknownKeyException
我知道我需要改变我的 RestKit 映射方法。对于复杂的情况
即使在简单的情况下,我也只是返回一个指向对象的指针。
RKObjectMapping *statusResponseMapping = [RKObjectMapping mappingForClass:[StatusResponse class]];
[statusResponseMapping addAttributeMappingsFromDictionary:@{@"status":@"status"}];
RKResponseDescriptor *statusResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:statusResponseMapping method:RKRequestMethodPOST pathPattern:nil keyPath:@"response" statusCodes:statusCodes];
我从服务器收到正确的响应...但只得到一个指针
response.body={
"response": {
"status": "ok"
}
}
2014-05-07 17:11:47.362 MyApp[145:60b] It Worked: {
response = "<StatusResponse: 0x16ee2e10>";
}
我缺少关键步骤或映射定义。我几乎达到了预期的效果。
我需要做什么才能在简单和复杂的情况下都获得预期的结果?
用下面的新信息更新了我的问题
2014 年 5 月 8 日今天更新,我将位置映射代码更改为...
RKObjectMapping *locationsMapping = [RKObjectMapping mappingForClass:[Locations class]];
[locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"locations" toKeyPath:@"locations" withMapping:locationMapping]];
这使它更接近正确映射。结果是……
2014-05-08 13:28:17.795 MyApp[165:60b] It Worked: {
locations = (
"<Locations: 0x14e69a10>",
"<Locations: 0x14e695c0>"
);
这几乎是正确的。我似乎缺少 cityKey 和 StateKey 的映射。我还没有定义 Description 方法。这是返回的原始 JSON 数据...
response.body={
"locations": [
{
"distance": 0.6,
"major": 2,
"minor": 4
},
{
"distance": 1.0,
"major": 2,
"minor": 11
}
],
"cityKey": "11",
"stateKey": "21"
}
映射不返回 cityKey 和 stateKey...映射定义中仍然缺少某些内容?
按照建议更改位置映射后于 2014 年 5 月 9 日更新
RKObjectMapping *locationsMapping = [RKObjectMapping mappingForClass:[Locations class]];
[locationsMapping addAttributeMappingsFromArray:@[
@"cityKey",@"stateKey"]];
[locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"locations" toKeyPath:@"locations" withMapping:locationMapping]];
response.body={
"locations": [
{
"distance": 0.6,
"major": 2,
"minor": 4
},
{
"distance": 1.0,
"major": 2,
"minor": 11
}
],
"cityKey": "10",
"stateKey": "15"
}
2014-05-09 13:18:17.669 MyApp[211:60b] It Worked: {
locations = (
"<Locations: 0x1780341e0>",
"<Locations: 0x170027c40>"
);
}
仍然缺少 cityKey 和 stateKey...不确定接下来要尝试什么?
于 2014 年 5 月 12 日更新以解决响应描述符...
我有两个响应描述符。我错过了在原始描述中发布一个。
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:locationMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"locations" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKResponseDescriptor *locationDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:locationsMapping method:RKRequestMethodAny pathPattern:@"/location" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
[[RKObjectManager sharedManager] addResponseDescriptor:locationDescriptor];
我按照建议更改了结构,但仍然缺少 cityKey 和 stateKey...我应该只使用一个响应描述符吗?
我找到了“使用多个 ResponseDescriptor?”的答案。在本文中http://www.softwarepassion.com/parsing-complex-json-with-objective-c-and-restkit/
当我查看作者如何定义他的 POJO 时,我发现只需要一个 ResponseDescriptor。其余的在关系的映射和定义中处理......
2014 年 5 月 15 日更新
我测试了响应描述符。只有一个人实际上正在努力产生“它有效”的结果。 locationDescriptor 根本不起作用。单独使用时会产生错误。当用作该对的一部分时,它被忽略了。与位置数据一致地传递“It works”的描述符是 responseDescriptor,其 keyPath 为 @"locations"。
我读过http://blog.mobilejazz.cat/ios-using-kvc-to-parse-json/
我有一个关于“...是您创建但没有描述方法实现的自定义类的预期日志输出”的问题。描述方法实现是什么意思?我需要添加什么才能将以下内容更改为映射结果的 NSArray 或 NSDictionary?您能否根据以下位置分享一个示例?
2014-05-09 13:18:17.669 MyApp[211:60b] It Worked: {
locations = (
"<Locations: 0x1780341e0>",
"<Locations: 0x170027c40>"
);
2014 年 5 月 16 日更新,向类实现文件添加了建议的 NSSTRING 描述
response.body={
"response": {
"status": "ok"
}
}
2014-05-16 10:32:26.260 MyApp[202:60b] It Worked: {
response = "status: ok";
}
因此,我计算了 NSString 描述方法实现已回答并正常工作。
更新的第二部分是使用方法描述符,我可以看到我没有将映射的 JSON 转换为数据结构值,而是我得到了 NULL
response.body={
"locations": [
{
"distance": 0.0,
"major": 2,
"minor": 8,
},
{
"distance": 3.5,
"major": 2,
"minor": 9,
},
{
"distance": 2.6575364531836625,
"major": 2,
"minor": 10,
}
],
"cityKey": "10",
"stateKey": "21"
}
2014-05-16 09:48:08.328 MyApp[189:60b] It Worked: {
locations = (
"location: (null) city: (null) state: (null)",
"location: (null) city: (null) state: (null)",
"location: (null) city: (null) state: (null)"
);
}
第一个问题是我应该为字典数组中的三个位置以及一个 cityKey 和一个 stateKey 获取位置 { distance, major, minor}。这是映射代码
RKObjectMapping* locationMapping = [RKObjectMapping mappingForClass:[Location class]];
[locationMapping addAttributeMappingsFromDictionary:@{
@"distance": @"distance",
@"major": @"major",
@"minor": @"minor"
}];
RKObjectMapping *locationsMapping = [RKObjectMapping mappingForClass:[Locations class]];
[locationsMapping addAttributeMappingsFromArray:@[ @"cityKey",@"stateKey"]];
[locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"locations" toKeyPath:@"locations" withMapping:locationMapping]];
//05/16/2014 this ResponseDesciptor is working
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:locationsMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"locations" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[[RKObjectManager sharedManager] addResponseDescriptor:responseDescriptor];
为什么它会为每个位置返回多个 cityKey 和 stateKey?为什么 JSON 数据返回时结果显示为 null?
2014 年 5 月 19 日更新 keyPath 设置为 nil 而不是 @"locations" 时抛出异常
2014-05-19 10:53:53.902 MyApp[245:4907] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Locations 0x17022d960> valueForUndefinedKey:]: this class is not key value coding-compliant for the key locations.'
*** First throw call stack:
代码提升它 RestKit 代码行 364
if ([self.dataSource respondsToSelector:@selector(mappingOperationShouldSetUnchangedValues:)] && [self.dataSource mappingOperationShouldSetUnchangedValues:self]) return YES;
id currentValue = [self.destinationObject valueForKeyPath:keyPath];
if (currentValue == [NSNull null]) {
currentValue = nil;
}
Locations 类头文件
#import <Foundation/Foundation.h>
@class Location;
@interface Locations : NSObject
@property (nonatomic, copy) Location *location;
@property (nonatomic, copy) NSString *cityKey;
@property (nonatomic, copy) NSString *stateKey;
@end
位置类实现文件
#import "Locations.h"
@implementation Locations
-(NSString *)description {
return [NSString stringWithFormat:@"location: %@ cityKey: %@ stateKey: %@", self.location, self.cityKey, self.stateKey];
}
@end
更改位置类属性来自
@property (nonatomic, copy) Location *location;
到
@property (nonatomic, copy) NSMutableArray *locations;
当 keyPath 为 nil 时收到期望的结果
response.body={
"locations": [
{
"distance": 0.0,
"major": 2,
"minor": 8
},
{
"distance": 3.5,
"major": 2,
"minor": 9
},
{
"distance": 2.6575364531836625,
"major": 2,
"minor": 10
}
],
"cityKey": "1",
"stateKey": "1"
}
2014-05-19 14:19:45.040 MyApp[290:60b] It Worked: {
"<null>" = "location: (\n \"distance: 0 major: 2 minor: 8 \",\n \"distance: 3.5 major: 2 minor: 9 \",\n \"distance: 2.657536453183662 major: 2 minor: 10 \"\n) cityKey: 1 stateKey: 1";
}
解决了这个问题。
【问题讨论】:
-
@Wain 在您的帮助下,我更接近于映射 JSON 响应数据。我缺少映射中的第二个、cityKey 和第三个、stateKey、顶级 JSON 对象。我还需要创建一个描述方法实现。请查看并让我知道您的想法。谢谢
-
@Wain 我按照建议更改了位置映射。我收到了没有 cityKey 和 stateKey 的相同位置。不知道接下来要尝试什么...我发布了代码以便您查看。谢谢
-
@Wain 在原始发布中,我错过了发布我的两个 ResponseDescriptor 之一。我更新了帖子以反映两个响应描述符和您的建议。我仍然缺少 cityKey 和 stateKey。我应该只使用一个 ResponseDescriptor 吗?
-
@Wain 我在我的问题中添加了这个发现的参考softwarepassion.com/…...我正在查看 ResKit 对象映射 wiki、此博客帖子和您的建议...我将发布我的结果
-
我不知道您是否应该有 2 个响应描述符,因为它们具有不同的路径模式。我希望位置映射应该有一个 nil 键路径,我会删除另一个响应描述符,直到你让第一部分工作
标签: ios objective-c json restkit restkit-0.20