在 Objective C 中使用 RestKit 解析复杂的 JSON

发布于 2024-12-29 14:26:24 字数 1626 浏览 2 评论 0原文

几天来我一直遇到这个问题,如果有人能够为此提供一些指导甚至完整的代码解决方案,我将非常感激。 我正在尝试使用 RestKit 在 Objective C 中执行到 JSON 字符串的动态对象映射,但似乎无法获得正确的值。 这是我需要解析的 JSON 响应类型的示例:

{
    "Boy" :
    {
        "favoriteClass" : "math",
        "basicInfo" :
        {
           "name" : "John",
           "age"  : 10,
           "type" : 1
        }
        "friends" :
        [
           {
              "Boy" :
              {
                 "favoriteClass" : "PE"
                 "basicInfo" :
                 {
                    "name" : "Bill",
                    "age" : 12,
                    "type" : 1
                 }
                 "friends" : []
              },
              "Girl" :
              {
                 "favoriteTeacher" : "Mrs. Manson"
                 "basicInfo" :
                 {
                    "name" : "Sara",
                    "age" : 11,
                    "type" : 2
                 }
                 "friends" : []
              },
              "Girl" :
              {
                 "favoriteTeacher" : "Mr. Chase"
                 "basicInfo" :
                 {
                    "name" : "Ronda",
                    "age" : 9,
                    "type" : 2
                 }
                 "friends" : []
              }
           }
        ]
    }
}

意思是,我有两种类型的类:Buy 类和 Girl 类。 他们每个都有不同的字段(男孩的favoriteClass和女孩的favoriteTeacher),但是两者都有一个basicInfo字段,其中包含完全相同的结构。 我可以使用数组中的记录名称(“Boy”或“Girl”)或通过“type”字段中的值来判断哪个应该映射到 Boy 类,哪个应该映射到 Girl 类。 “basicInfo”记录(男孩 1 个,女孩 2 个)。 Boy 和 Girl 类的朋友数组可以包含男孩和女孩的实例。

有人可以给我一些关于如何做到这一点的指示吗? 任何帮助将不胜感激。

谢谢,

I've been having issues with this issue for several days now, and would really appreciate it if someone will be able to provide some guidance or even a full code solution for this.
I'm trying to perform dynamic object mapping to a JSON string in Objective C using RestKit and can't seem to get the right values.
This is an example to the kind of JSON response I need to parse:

{
    "Boy" :
    {
        "favoriteClass" : "math",
        "basicInfo" :
        {
           "name" : "John",
           "age"  : 10,
           "type" : 1
        }
        "friends" :
        [
           {
              "Boy" :
              {
                 "favoriteClass" : "PE"
                 "basicInfo" :
                 {
                    "name" : "Bill",
                    "age" : 12,
                    "type" : 1
                 }
                 "friends" : []
              },
              "Girl" :
              {
                 "favoriteTeacher" : "Mrs. Manson"
                 "basicInfo" :
                 {
                    "name" : "Sara",
                    "age" : 11,
                    "type" : 2
                 }
                 "friends" : []
              },
              "Girl" :
              {
                 "favoriteTeacher" : "Mr. Chase"
                 "basicInfo" :
                 {
                    "name" : "Ronda",
                    "age" : 9,
                    "type" : 2
                 }
                 "friends" : []
              }
           }
        ]
    }
}

Meaning, I have two types of classes: a Buy class and a Girl class.
They each have different fields (favoriteClass for the boys and favoriteTeacher for the girls), but the both have a basicInfo field, which contains exactly the same structure.
I can tell which should be mapped to the Boy class and which should be mapped to the Girl class with using the name of the record in the array ("Boy" or "Girl"), or by the "type" field's value within the "basicInfo" record (1 for boys and 2 for girls).
The friends array for both a Boy and a Girl class can contain instances of both boys and girls.

Can anybody please give me some pointers on how this can be done?
Any help will be greatly appreciated.

Thanks,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

意中人 2025-01-05 14:26:24

我今天才开始研究 RestKit,所以我离权威还很远。然而,看看 Blake 的优秀文档,在我看来,你把这个问题过于复杂化了(你发布的 JSON 并没有验证 BTW)。除非您有特定需要拥有 BasicInfo 对象,否则我会删除它并配置您的 JSON:

{
    "people": [
        {
            "age": 10, 
            "favoriteClass": "math", 
            "name": "John", 
            "type": 1,
            "friends": [
                {
                    "age": 12, 
                    "favoriteClass": "PE", 
                    "friends": [], 
                    "name": "Bill", 
                    "type": 1
                }, 
                {
                    "age": 11, 
                    "favoriteTeacher": "Mrs. Manson", 
                    "friends": [], 
                    "name": "Sara", 
                    "type": 2
                }, 
                {
                    "age": 9, 
                    "favoriteTeacher": "Mr. Chase", 
                    "friends": [], 
                    "name": "Ronda", 
                    "type": 2
                }
            ] 
        }
    ]
}

然后您应该能够利用他在 Dynamic 中描述的方法 (1) 对象映射文档的对象映射部分。 a> 看来我认为与他给出的示例相比,您的唯一区别是您在每个 BoyGirl 类中都有一些额外的 ivars,并且您使用的是一个数字而不是一个字符串来识别 BoyGirl。您可以通过修改他给出的声明来解决这个问题:

// Basic setup
RKObjectMapping* boyMapping = [RKObjectMapping mappingForClass:[Boy class]];
[boyMapping mapAttributes:@"age", @"name", @"favoriteClass",nil];

RKObjectMapping* girlMapping = [RKObjectMapping mappingForClass:[Girl class]];
[girlMapping mapAttributes:@"age", @"name", @"favoriteTeacher", nil];

// Configure the dynamic mapping via matchers
[dynamicMapping setObjectMapping:boyMapping whenValueOfKeyPath:@"type" isEqualTo:@"1"];
[dynamicMapping setObjectMapping:girlMapping whenValueOfKeyPath:@"type" isEqualTo:@"2"];

匹配器的类型可能不太正确——正如我所说,我今天才开始阅读这些内容。

I just started looking at RestKit today, so I am far from an authority. However, looking at Blake's excellent documentation, it seems to me that you are overly complicating this (your posted JSON does not validate BTW). Unless you have a specific need to have a BasicInfo object, I'd remove it and configure your JSON thus:

{
    "people": [
        {
            "age": 10, 
            "favoriteClass": "math", 
            "name": "John", 
            "type": 1,
            "friends": [
                {
                    "age": 12, 
                    "favoriteClass": "PE", 
                    "friends": [], 
                    "name": "Bill", 
                    "type": 1
                }, 
                {
                    "age": 11, 
                    "favoriteTeacher": "Mrs. Manson", 
                    "friends": [], 
                    "name": "Sara", 
                    "type": 2
                }, 
                {
                    "age": 9, 
                    "favoriteTeacher": "Mr. Chase", 
                    "friends": [], 
                    "name": "Ronda", 
                    "type": 2
                }
            ] 
        }
    ]
}

Then you should be able to utilize approach (1) that he describes in the Dynamic Object Mapping section of the Object Mapping document. It appears to me that the only difference you have in comparison with the example he gives is that you have some additional ivars in each of the Boy and Girl classes, and you are using an number rather than a string to identify Boy vs Girl. You can deal with that by modifying the declarations he gives to be:

// Basic setup
RKObjectMapping* boyMapping = [RKObjectMapping mappingForClass:[Boy class]];
[boyMapping mapAttributes:@"age", @"name", @"favoriteClass",nil];

RKObjectMapping* girlMapping = [RKObjectMapping mappingForClass:[Girl class]];
[girlMapping mapAttributes:@"age", @"name", @"favoriteTeacher", nil];

// Configure the dynamic mapping via matchers
[dynamicMapping setObjectMapping:boyMapping whenValueOfKeyPath:@"type" isEqualTo:@"1"];
[dynamicMapping setObjectMapping:girlMapping whenValueOfKeyPath:@"type" isEqualTo:@"2"];

The type of the matcher may not be quite right -- as I said, I just started reading this stuff today.

无需解释 2025-01-05 14:26:24

只需以有纪律的方式遍历层次结构即可。

//pseudo code
for (id child in JSONObject) {
   if (it is a boy) create new boy object;
   else             create new girl object;
   fill in the info;
   for (id child in friends) {
      if (it is a boy) create new boy object;
      else             create new girl object;
      fill in the info;
   }
}

当然,整个数据方案重复得可笑。在我看来,你应该只有一个类Child,无论如何它都有一个属性basicInfo.type来标识它是男孩还是女孩,所以不需要有一个额外的类。

另外,如果您有一个彼此是朋友的孩子的列表,您最终会多次列出许多孩子。更好的做法是在好友字段中使用一个具有唯一 ID 的简单数组。

Just go through the hierarchy in a disciplined way.

//pseudo code
for (id child in JSONObject) {
   if (it is a boy) create new boy object;
   else             create new girl object;
   fill in the info;
   for (id child in friends) {
      if (it is a boy) create new boy object;
      else             create new girl object;
      fill in the info;
   }
}

Of course the whole data scheme is ridiculously repetitive. In my opinion, you should have only one class Child that anyway has an attribute basicInfo.type that identifies it as boy or girl, so no need to have an extra class.

Also, if you have a list of children who are friends with each other, you will end up listing many children multiple times. Much better would be to have a simple array with unique IDs in the friends field.

自由如风 2025-01-05 14:26:24

您只需要使用像 SBJSON 这样的 JSON 解析器,SBJSON 可以解析您收到的数据,如下所示:

SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *received = [parser objectWithData:data];

但是,如果您想使用 Restkit,它也有一个内置解析器。我相信它会起到这样的作用:

- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response 
{
    RKJSONParser* parser = [RKJSONParser new]; 
    NSDictionary *dict = [parser objectFromString:[response bodyAsString]]; 
}

我希望对您有所帮助。

You simply need to use a JSON parser like SBJSON, SBJSON can parse the data you receive like so:

SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *received = [parser objectWithData:data];

However, if you want to use Restkit, it has a built in parser also. I believe it would work something like this:

- (void)request:(RKRequest*)request didLoadResponse:(RKResponse*)response 
{
    RKJSONParser* parser = [RKJSONParser new]; 
    NSDictionary *dict = [parser objectFromString:[response bodyAsString]]; 
}

I hope that helps you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文