【问题标题】:How to parse nested JSON objects with JSON framework and Objective-C/iPhone/Xcode?如何使用 JSON 框架和 Objective-C/iPhone/Xcode 解析嵌套的 JSON 对象?
【发布时间】:2010-10-16 02:07:48
【问题描述】:

我正在使用 JSON 框架编写一个 iPhone 原生应用程序。

我的应用正在使用 JSON 访问 Web 服务。我们发送的 JSON 数据有嵌套对象,下面是提供的数据示例:

{
    "model": {
        "JSONRESPONSE": {
            "authenticationFlag": true,
            "sessionId": "3C4AA754D77BFBE33E0D66EBE306B8CA",
            "statusMessage": "Successful Login.",
            "locId": 1,
            "userName": "Joe Schmoe"
        }
    }
}

我在使用 objectForKey 和 valueForKey NSDictionary 方法进行解析时遇到问题。我不断收到 invalidArgumentException 运行时错误。

例如,我想查询“authenticationFlag”元素的响应数据。

谢谢, 麦克风 西雅图

【问题讨论】:

    标签: objective-c iphone xcode json


    【解决方案1】:

    如果没有更多细节(例如您正在使用的 JSON 解析代码),很难说,但有两件事让我印象深刻:

    1. 您没有使用完整路径进行查询。在上述情况下,您需要首先获取封闭模型、json 响应,然后才向 json 响应字典询问 authenticationFlag 值:

      [[[jsonDict objectForKey:@"model"] objectForKey:@"JSONRESPONSE"] objectForKey:@"authenticationFlag"]

    2. 也许您使用 c-strings ("") 而不是 NSStrings (@"") 作为键(尽管这可能会严重崩溃或无法编译)。键应该是不能转换为 id 的东西。

    虽然可能,但两者都可能是错误的,所以请提供更多细节。

    【讨论】:

    • 解决方案 1 有效。本质上,我需要向下遍历到 JSONRESPONSE 节点,然后才能访问所需的元素。谢谢!
    【解决方案2】:

    以下内容直接取自 Dan Grigsby 的教程 - http://mobileorchard.com/tutorial-json-over-http-on-the-iphone/ - 请注明,偷窃是恶业。

    通过 HTTP 获取 JSON

    我们将使用 Cocoa 的 NSURLConnection 发出 HTTP 请求并检索 JSON 数据。

    Cocoa 为发出 HTTP 请求提供同步和异步选项。从应用程序的主运行循环运行的同步请求会导致应用程序在等待响应时停止。异步请求使用回调来避免阻塞并且易于使用。我们将使用异步请求。

    我们需要做的第一件事是更新视图控制器的接口,以包含一个 NSMutableData 来保存响应数据。我们在接口中声明这一点(而不是在方法中),因为响应是以我们拼接在一起的片段连续返回的,而不是一个完整的单元。

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController {
        IBOutlet UILabel *label;
        NSMutableData *responseData;
    }
    

    为简单起见,我们将从 viewDidLoad 启动 HTTP 请求。

    替换以下内容:

    #import "JSON/JSON.h"
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        responseData = [[NSMutableData data] retain];
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"XYZ.json"]];
        [[NSURLConnection alloc] initWithRequest:request delegate:self];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
        [responseData setLength:0];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
        [responseData appendData:data];
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
        label.text = [NSString stringWithFormat:@"Connection failed: %@", [error description]];
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        [connection release];
    }
    
    - (void)dealloc {
        [super dealloc];
    }
    
    @end
    

    这主要是样板代码初始化 responseData 变量以准备好保存数据并在 viewDidload 中启动连接;当它们进入 didReceiveData 时,它会收集碎片;并且空的 connectionDidFinishLoading 准备好对结果做一些事情。 使用 JSON 数据

    接下来,我们将充实 connectionDidFinishLoading 方法,以利用在上一步中检索到的 JSON 数据。

    更新connectionDidFinishLoading方法:

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        [connection release];
    
        NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
        [responseData release];
    
        NSArray *luckyNumbers = [responseString JSONValue];
    
        NSMutableString *text = [NSMutableString stringWithString:@"Lucky numbers:\n"];
    
        for (int i = 0; i < [luckyNumbers count]; i++)
            [text appendFormat:@"%@\n", [luckyNumbers objectAtIndex:i]];
    
        label.text =  text;
    }
    

    它创建一个 NSArray。解析器非常灵活并返回对象——包括嵌套对象——将 JSON 数据类型与 Objective-C 数据类型适当匹配。 更好的错误处理

    到目前为止,我们一直在使用方便的高级扩展 NSString 方法来解析 JSON。我们这样做是有充分理由的:将 JSONValue 消息简单地发送到字符串以访问解析的 JSON 值是很方便的。

    不幸的是,使用这种方法会使有用的错误处理变得困难。如果 JSON 解析器由于任何原因失败,它只会返回一个 nil 值。但是,如果您在发生这种情况时查看控制台日志,您会看到准确描述导致解析器失败的原因的消息。

    如果能够将这些错误详细信息传递给用户,那就太好了。为此,我们将切换到 JSON SDK 支持的第二种面向对象的方法。

    更新connectionDidFinishLoading方法:

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        [connection release];
    
        NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
        [responseData release];
    
        NSError *error;
        SBJSON *json = [[SBJSON new] autorelease];
        NSArray *luckyNumbers = [json objectWithString:responseString error:&error];
        [responseString release];   
    
        if (luckyNumbers == nil)
            label.text = [NSString stringWithFormat:@"JSON parsing failed: %@", [error localizedDescription]];
        else {
            NSMutableString *text = [NSMutableString stringWithString:@"Lucky numbers:\n"];
    
            for (int i = 0; i < [luckyNumbers count]; i++)
                [text appendFormat:@"%@\n", [viewcontroller objectAtIndex:i]];
    
            label.text =  text;
        }
    }
    

    使用此方法为我们提供了一个指向底层 JSON 解析器的错误对象的指针,我们可以将其用于更有用的错误处理。

    结论:

    JSON SDK 和 Cocoa 对 HTTP 的内置支持使得将 JSON Web 服务添加到 iPhone 应用程序变得简单。

    【讨论】:

    • 我有这样的json格式,请问如何使用,请帮帮我。 jsont({ "id": "ntp-a1.nict.go.jp", "it": 1232963971.248, "st": 1344228610.961, "leap": 34, "next": 1341100800, "step": 1 })
    【解决方案3】:
        NSString* aStr;
        aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
        NSDictionary *dictionary = [aStr JSONValue];
        NSArray *keys = [dictionary allKeys];
    
        // values in foreach loop
        for (NSString *key in keys) {
        NSArray *items = (NSArray *) [dictionary objectForKey:key];  
    
            for (id *item in items) {  
    
    
                NSString* aStrs=  item;
                NSLog(@" test %@", aStrs);
    
                NSDictionary *dict = aStrs;
                NSArray *k = [dict allKeys];
    
            for (id *it in k) {  
                                NSLog(@"the  child item: %@", [NSString stringWithFormat:@"Child Item -> %@ value %@", (NSDictionary *) it,[dict objectForKey:it]]);                
                            }
    

    【讨论】:

      【解决方案4】:

      现在,Objective c 已经在构建类中引入了 JSON Parsing。

       NSError *myError = nil;
       NSDictionary *resultDictionary = [NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:&myError];
      

      http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html

      所以利用这个类,让你的应用程序没有错误...:)

      【讨论】:

        猜你喜欢
        • 2011-03-11
        • 2011-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多