RestKit复杂而简单的JSON RKObjectMapping几乎可以工作,但是 [英] RestKit complex and simple JSON RKObjectMapping almost working, but

查看:122
本文介绍了RestKit复杂而简单的JSON RKObjectMapping几乎可以工作,但是的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究这个问题.这是一些发现,将有助于在RestKit中映射此JSON响应

I have been researching this issue.  Here are a few discoveries that will help map this JSON response in RestKit

JSON响应对象包含三个顶级对象: 位置是一个数组 cityKey对象
stateKey对象

The JSON response object contains three top level objects : locations is an array cityKey object
stateKey object

Since Restkit is written in Objective-C, I looked at it as if I were going to directing映射这些对象并解析出数据

Since Restkit is written in Objective-C, I looked at it as if I were going to directing map these objects and parse-out data

我编写了以下代码来映射Location Class \ Object的NSDictionary部分:

I wrote the following code to map the NSDictionary portion of the Location Class\Object:

    RKObjectMapping* locationMapping = [RKObjectMapping       mappingForClass:[Location class]];
     [locationMapping addAttributeMappingsFromDictionary:@{
                             @"distance": @"distance",
                             @"major": @"major",
                             @"minor": @"minor" }];

我为整个class \ object位置编写了以下代码://这也应该是NSDictionary

I wrote the following code for the overall class\object , Locations: //This should also be an NSDictionary

    RKObjectMapping *locationsMapping = RKObjectMapping       mappingforclass: [Locations class]];

This appears to be a mapping array should be a dictionary.

    [locationsMapping addAttributeMappingsFromArray:@[@"locations", @"cityKey",@"stateKey"]];

我看到在将Array用于整个对象的位置时出错.这将运行并返回以下内容的部分成功结果:

I see the error in the use of Array for the overall object Locations. This runs and returns a partially successful result from the following:

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的动态映射会解决此复杂的JSON映射?

将已解析的数据馈送到RKMapperOperation会引发NSUnknownKeyException

我知道我需要更改RestKit映射的方法.对于复杂的情况

I know that I need to change my approach to RestKit mapping. For the complex case

即使在简单的情况下,我也只返回一个指向对象的指针.

Even in the simple case, I am only returning a pointer to the object.

 RKObjectMapping *statusResponseMapping = [RKObjectMapping mappingForClass:[StatusResponse class]];

    [statusResponseMapping addAttributeMappingsFromDictionary:@{@"status":@"status"}]; 

RKResponseDescriptor *statusResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:statusResponseMapping method:RKRequestMethodPOST pathPattern:nil keyPath:@"response" statusCodes:statusCodes];

我从服务器收到了正确的响应...但是只得到了一个指针

I receive the correct response from the server...but only get a pointer

 response.body={
      "response": {
        "status": "ok"
      }
    }
    2014-05-07 17:11:47.362 MyApp[145:60b] It Worked: {
        response = "<StatusResponse: 0x16ee2e10>";

    }

我缺少关键步骤或映射定义.我几乎达到了预期的结果.

I am missing key step or mapping definition. I am almost to the desired result.

在简单和复杂的情况下,我需要怎么做才能获得理想的结果?

What do I need to do to get the desired results in both the simple and complex cases?

使用以下新信息更新了我的问题

UPDATED MY QUESTION WITH THE NEW INFORMATION BELOW

2014年5月8日今天更新,我将位置映射代码更改为...

Updated today may 8 2014, I changed locationsMapping code to...

RKObjectMapping *locationsMapping = [RKObjectMapping mappingForClass:[Locations class]];
    [locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"locations" toKeyPath:@"locations" withMapping:locationMapping]];

将其移至更接近正确映射的位置.结果是...

Which moved it a step closer to correctly mapping. The result was...

2014-05-08 13:28:17.795 MyApp[165:60b] It Worked: {
    locations =     (
        "<Locations: 0x14e69a10>",
        "<Locations: 0x14e695c0>"
    );

这几乎是正确的.我似乎缺少cityKey和StateKey的映射.我尚未定义Description方法.这是返回的原始JSON数据...

Which is almost correct. I appear to be missing mapping for the cityKey and StateKey. I have not defined the Description method. Here is the raw JSON data returned...

response.body={
  "locations": [
    {
      "distance": 0.6, 
      "major": 2, 
      "minor": 4 

    }, 
    {
      "distance": 1.0, 
      "major": 2, 
      "minor": 11 

    }
  ], 
  "cityKey": "11", 
  "stateKey": "21"
}

映射不返回cityKey和stateKey ...映射定义中仍然缺少某些内容吗?

Mapping does not return the cityKey and stateKey...something is still missing in the mapping definition?

在更改位置后于2014年5月9日更新

UPDATED MAY 9 2014 AFTER CHANGING locationMapping as suggested

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 ...不确定接下来要尝试什么?

Still missing cityKey and stateKey...not sure what to try next?

2014年5月12日已更新,以解决响应者...

UPDATED 05/12/2014 TO ADDRESS RESPONSE DESCRIPTORS...

我有两个响应描述符.我错过了在原始说明中张贴一个.

I had two response descriptors. I missed posting one in the original description.

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 ...我应该只使用一个响应描述符吗?

I changed the structure as recommended but I am still missing the cityKey and stateKey...should I use only one Response Descriptor?

我找到了使用多个ResponseDescriptor?"的答案.本文 http://www.softwarepassion .com/parsing-complex-json-with-objective-c-and-restkit/

I found an answer to the "use more than one ResponseDescriptor?" here in this article http://www.softwarepassion.com/parsing-complex-json-with-objective-c-and-restkit/

当我回顾作者如何定义他的POJO时,我发现只需要一个ResponseDescriptor.其余的在关系的映射和定义中处理...

When I reviewed how the author defined his POJOs, I discovered that only one ResponseDescriptor was required. The rest is handled in the mapping and defining of relationships...

2014年5月15日更新

UPDATED MAY 15 2014

我测试了响应描述符.实际上只有一个人在努力产生成功"的结果. locationDescriptor根本不起作用.单独使用时会产生错误.用作配对中的一部分时,将其忽略.始终使用位置数据传递工作原理"的描述符是带有keyPath的@Delocations的responseDescriptor.

I tested the response descriptors. Only one was actually working to generate the "It worked" result. The locationDescriptor was not working at all. It generated an error when used alone. It was ignored when used as a part of the pair. The descriptor that consistently delivered the "It works" with locations data was responseDescriptor with the keyPath as @"locations".

我阅读了 http://blog.mobilejazz.cat/ios-using-kvc-to-parse-json/

我有一个问题:"...是您创建的自定义类的预期日志输出,但是它没有描述方法的实现."描述方法的实现是什么意思?我需要添加什么才能将以下内容更改为映射结果的NSArray或NSDictionary?您能否根据以下位置分享一个示例?

I have a question about "...is the expected log output from a custom class that you create but which doesn't have a description method implementation." What is meant by description method implementation? What do I need to add to change the following into an NSArray or NSDictionary of mapping results? Could you share an example based on locations below?

2014-05-09 13:18:17.669 MyApp[211:60b] It Worked: {
        locations  =     (
            "<Locations: 0x1780341e0>",
            "<Locations: 0x170027c40>"
        );

2014年5月16日更新,为实现文件添加了建议的NSSTRING描述

UPDATED MAY 16 2014 ADDED SUGGESTED NSSTRING DESCRIPTION TO CLASS IMPLEMENTATION FILES

response.body={
  "response": {
    "status": "ok"
  }
}
2014-05-16 10:32:26.260 MyApp[202:60b] It Worked: {
    response = "status: ok";
}

因此,我计算了NSString描述方法实现的答案,并且可以正常工作.

Therefore, I count the NSString description method implementation answered and working correctly.

第二部分更新与方法描述符有关,我可以看到我没有将映射的JSON替换为数据结构值,而我却获取了NULL

SECOND PART OF THE UPDATE IS WITH METHOD DESCRIPTORS IN PLACE I CAN SEE THAT I AM NOT GETTING THE MAPPED JSON TO DATA STRUCTURE VALUES INSTEAD I AM GETTING 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}.这是映射代码

First issue is that I should get a location { distance, major, minor} for the three locations in the array of dictionaries and one cityKey and one stateKey. Here is the mapping code

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数据返回时结果显示为空?

Why is it returning multiple cityKey and stateKey for each location? Why are the results showing null when JSON data returns?

在keyPath设置为nil而不是@"locations"时抛出异常2014年5月19日

UPDATED MAY 19 2014 EXCEPTION THROWN when keyPath is set to nil and not @"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:

RAISING IT RestKit代码行364

CODE RAISING IT RestKit code line 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类头文件

Locations Class header file

#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

Locations Class Implementation文件

Locations Class Implementation file

#import "Locations.h"

@implementation Locations

-(NSString *)description {

    return [NSString stringWithFormat:@"location: %@ cityKey: %@ stateKey: %@", self.location, self.cityKey, self.stateKey];
}

@end   

位置更改后的位置类属性

CHANGED LOCATIONS CLASS PROPERTY FROM

@property (nonatomic, copy) Location *location; 

TO

@property (nonatomic, copy) NSMutableArray *locations;

当keyPath为nil时获得所需的结果

RECEIVED THE DESIRED RESULT when keyPath is 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";
}

解决了这个问题.

推荐答案

创建locationsMapping时,应使用locationMapping@"locations"作为关系添加(不直接作为属性).

When you create locationsMapping, @"locations" should be added as a relationship using locationMapping (not directly as an attribute).

您应该有一个使用locationsMapping的响应描述符.

You should have a response descriptor that uses locationsMapping.

此:

2014-05-07 17:11:47.362 MyApp[145:60b] It Worked: {
    response = "<StatusResponse: 0x16ee2e10>";
}

是您创建的但没有description方法实现的自定义类的预期日志输出.

is the expected log output from a custom class that you create but which doesn't have a description method implementation.

RKObjectMapping *locationsMapping = [RKObjectMapping mappingForClass:[Locations class]];
[locationsMapping addAttributeMappingsFromArray:@[@"cityKey", @"stateKey"]];
[locationsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"locations" toKeyPath:@"locations" withMapping:locationMapping]];


在您的Locations类上,添加:


On your Locations class add:

- (NSString *)description
{
    return [NSString stringWithFormat:@"city:%@ state:%@ locations:%@", self.cityKey, self.stateKey, self.locations];
}

Location类的类似方法.

这篇关于RestKit复杂而简单的JSON RKObjectMapping几乎可以工作,但是的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆