Ios 使用NSJSONSerialization正确反序列化嵌套JSON提要?

Ios 使用NSJSONSerialization正确反序列化嵌套JSON提要?,ios,json,cocoa-touch,ios6,Ios,Json,Cocoa Touch,Ios6,我有一个很简单的问题,我想有经验的人很容易回答。有一个JSON提要,它将视频URL内容传送到im构建中的一个应用程序。看起来是这样的: { "playlist": [ { "videos": { "ds900": { "length": 30, "bitrate": "900", "uri"

我有一个很简单的问题,我想有经验的人很容易回答。有一个JSON提要,它将视频URL内容传送到im构建中的一个应用程序。看起来是这样的:

    {
    "playlist": [
        {
            "videos": {
                "ds900": {
                    "length": 30,
                    "bitrate": "900",
                    "uri": "http://somevideo1.mp4"
                },
                "ds300": {
                    "length": 30,
                    "bitrate": "300",
                    "uri": "http://somevideo2.mp4"
                },
                "ds500": {
                    "length": 30,
                    "bitrate": "500",
                    "uri": "http://somevideo3.mp4"
                },
                "ds700": {
                    "length": 30,
                    "bitrate": "700",
                    "uri": "http://somevideo4.mp4"
                }
            }
        }
    ],
    "playlistName": "The Play List Name",
    "description": "The description"
}
NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"] objectForKey:@"ds700"];
NSString *url = videoTypes[@"uri"];
NSLog(@"Val: %@", uri);
要对此进行反序列化,我有以下代码:

    -(void)connectToVideoLink
{
    NSString *urlString = @"http://Link_To_JSON_feed";
    NSURL *url = [NSURL URLWithString:urlString];

    NSURLRequest *urlRequest =
    [NSURLRequest requestWithURL:url
                     cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                 timeoutInterval:30.0f];


    NSOperationQueue *queue =[[NSOperationQueue alloc] init];

    [NSURLConnection sendAsynchronousRequest:urlRequest
                                       queue:queue
                           completionHandler:^(NSURLResponse *response,
                                               NSData *dataR,
                                               NSError *error) {

                               if([dataR length]>0 && error == nil)
                               {
                                   NSString *feed = [[NSString alloc] initWithData:dataR
                                                                          encoding:NSUTF8StringEncoding];
                                   [self trythis2:dataR];

                               }
                               else if ([dataR length]==0 && error==nil)
                               {
                                   NSLog(@"Nothing available");
                               }
                               else if (error != nil)
                               {
                                   NSLog(@"Error is : %@", error);
                               }

     }]; 
}
然后调用函数[self-trythis2:dataR];这将调用反序列化方法

-(void)trythis2:(NSData*)responseData
{
    NSError *e = nil;

    id jsonObject = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];

    NSDictionary *jsonArray = (NSDictionary *)jsonObject;
    jsonArray = [NSJSONSerialization JSONObjectWithData: responseData options: NSJSONReadingAllowFragments error: &e];
    //NSArray
    if (!jsonArray) {
        NSLog(@"Error parsing JSON: %@", e);
    } else {

        NSArray *playlistdict = [jsonArray objectForKey:@"playlist"];
        for (NSDictionary *playlistitems in playlistdict) {
            NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"] objectForKey:@"ds700"];
            NSLog(@"String: %@", videoTypes);
            for (NSDictionary *videoTypesItems in videoTypes) {
                NSLog(@"ds700 Key: %@", videoTypesItems);

                NSLog(@"Val : %@",[videoTypesItems objectForKey:@"uri"]); //error caused here


            }
        }
    }
}
如上所述,错误停止在注释行。这是我的输出:

2013-08-07 15:21:22.711 DeserializeJSON[3025:1d03] String: {
    bitrate = 700;
    length = 30;
    uri = "http://somevideo1.mp4";
}
2013-08-07 15:21:22.713 DeserializeJSON[3025:1d03] ds700 Key: bitrate
2013-08-07 15:21:22.714 DeserializeJSON[3025:1d03] -[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x1ed3e910
2013-08-07 15:21:22.715 DeserializeJSON[3025:1d03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x1ed3e910'
*** First throw call stack:
(0x33e853e7 0x3bb80963 0x33e88f31 0x33e8764d 0x33ddf208 0x72ee9 0x71fa3 0x3471c229 0x34713a89 0x3478bfe7 0x3bf9a793 0x3bf9e657 0x3bf9e7d9 0x3bfc27f1 0x3bfc2684)
libc++abi.dylib: terminate called throwing an exception
(lldb) 

我确信uri=“”;是可用的,但正如你所看到的,我不能抓住它。我尝试使用NSString变量,并在记录它之前尝试将[videoTypesItems objectForKey:@“uri”]分配给它,但这也不起作用。我在解析这个JSON时哪里出错了?感谢阅读。

您的
videoTypes
词典没有任何嵌套数据。你想要这样的东西:

    {
    "playlist": [
        {
            "videos": {
                "ds900": {
                    "length": 30,
                    "bitrate": "900",
                    "uri": "http://somevideo1.mp4"
                },
                "ds300": {
                    "length": 30,
                    "bitrate": "300",
                    "uri": "http://somevideo2.mp4"
                },
                "ds500": {
                    "length": 30,
                    "bitrate": "500",
                    "uri": "http://somevideo3.mp4"
                },
                "ds700": {
                    "length": 30,
                    "bitrate": "700",
                    "uri": "http://somevideo4.mp4"
                }
            }
        }
    ],
    "playlistName": "The Play List Name",
    "description": "The description"
}
NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"] objectForKey:@"ds700"];
NSString *url = videoTypes[@"uri"];
NSLog(@"Val: %@", uri);
如果确实要迭代字典的键,可以执行以下操作:

NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"] objectForKey:@"ds700"];
NSLog(@"String: %@", videoTypes);
for (NSString *videoTypeKey in [videoTypes allKeys]) {
    NSLog(@"ds700 Key: %@", videoTypeKey);

    NSLog(@"Val : %@", videoTypesItems[videoTypeKey]); //error caused here
}

您的
videoTypes
词典没有任何嵌套数据。你想要这样的东西:

    {
    "playlist": [
        {
            "videos": {
                "ds900": {
                    "length": 30,
                    "bitrate": "900",
                    "uri": "http://somevideo1.mp4"
                },
                "ds300": {
                    "length": 30,
                    "bitrate": "300",
                    "uri": "http://somevideo2.mp4"
                },
                "ds500": {
                    "length": 30,
                    "bitrate": "500",
                    "uri": "http://somevideo3.mp4"
                },
                "ds700": {
                    "length": 30,
                    "bitrate": "700",
                    "uri": "http://somevideo4.mp4"
                }
            }
        }
    ],
    "playlistName": "The Play List Name",
    "description": "The description"
}
NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"] objectForKey:@"ds700"];
NSString *url = videoTypes[@"uri"];
NSLog(@"Val: %@", uri);
如果确实要迭代字典的键,可以执行以下操作:

NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"] objectForKey:@"ds700"];
NSLog(@"String: %@", videoTypes);
for (NSString *videoTypeKey in [videoTypes allKeys]) {
    NSLog(@"ds700 Key: %@", videoTypeKey);

    NSLog(@"Val : %@", videoTypesItems[videoTypeKey]); //error caused here
}
videoTypes
中,您正在打开“ds700”字典。它不包含任何子字典,仅包含键值对。但是,for循环正在创建NSDictionary

    "ds700": {
        "length": 30,
        "bitrate": "700",
        "uri": "http://somevideo4.mp4"
    }
如果要循环浏览所有不同的视频类型(ds300、ds500、ds700和ds900),请尝试以下操作:

    NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"];
    NSLog(@"String: %@", videoTypes);
    for (NSDictionary *videoTypesItems in videoTypes) {
        NSLog(@"type Key: %@", videoTypesItems);

        NSLog(@"Val : %@",[videoTypesItems objectForKey:@"uri"]);


    }
videoTypes
中,您正在打开“ds700”字典。它不包含任何子字典,仅包含键值对。但是,for循环正在创建NSDictionary

    "ds700": {
        "length": 30,
        "bitrate": "700",
        "uri": "http://somevideo4.mp4"
    }
如果要循环浏览所有不同的视频类型(ds300、ds500、ds700和ds900),请尝试以下操作:

    NSDictionary *videoTypes = [[playlistitems objectForKey:@"videos"];
    NSLog(@"String: %@", videoTypes);
    for (NSDictionary *videoTypesItems in videoTypes) {
        NSLog(@"type Key: %@", videoTypesItems);

        NSLog(@"Val : %@",[videoTypesItems objectForKey:@"uri"]);


    }

你为什么把字典叫做“jsonArray”?在你来到这里之前你做得很好--
for(NSDictionary*videoTypesItems in videoTypes){
您好,是的,我不想让您感到困惑。因为我在NSArray和NSDictionary之间玩游戏,所以在发布之前忘了更改名称。谢谢您指出这一点。在处理JSON“解构”时,使用有意义的名称是非常关键的。同时请注意术语“嵌套JSON”通常是在JSON结构包含一个本身是有效JSON序列的(带引号的)字符串的情况下保留的。上面是一个相对简单的JSON结构,而不是按照该定义“嵌套”的。为什么要将字典称为“jsonArray”?在这里之前你做得很好--
(NSDictionary*videoTypesItems in videoTypes){
您好,是的,我不想把您弄糊涂。我在发布之前忘了更改名称,因为我在NSArray和NSDictionary之间玩。不过感谢您指出这一点。在处理JSON“解构”时,这非常关键,以使用有意义的名称。还请注意,术语“嵌套的JSON”通常用于JSON结构包含(带引号的)字符串的情况,该字符串本身是一个有效的JSON序列。以上是一个相对简单的JSON结构,而不是“嵌套的”根据这个定义。谢谢你的回答,Bo A。我尝试了你的解决方案,它看起来像是我以前实施的类似解决方案。它导致了相同的问题。谢谢你的回答,Bo A。我尝试了你的解决方案,它看起来像是我以前实施的类似解决方案。它导致了相同的问题。谢谢你的解决方案,我能够抓住问题URL。由于videoTypes目前是一个字典。videoTypes[@“uri”]和[videoTypesItems objectForKey:@“uri”]不是做同样的事情吗?除了前者似乎被视为数组之外?使用
videoTypes[@“uri”]
是现代语法,本质上与
[videoTypes objectForKey:@“uri”]
。感谢您提供的解决方案,我能够获取URL。因为videoTypes目前是一个字典。videoTypes[@“uri”]和[videoTypesItems objectForKey:@“uri”]不是做同样的事情吗?除了前者似乎被视为数组之外?使用
videoTypes[@“uri”]
是现代语法,本质上与
[videoTypes objectForKey:@“uri”]