如何使用 JSON 框架和 Objective-C/iPhone/Xcode 解析嵌套的 JSON 对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/692247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:13:41  来源:igfitidea点击:

How to parse nested JSON objects with JSON framework and Objective-C/iPhone/Xcode?

objective-ciphonexcodejson

提问by mibrop

I'm writing an iPhone native app using the JSON framework.

我正在使用 JSON 框架编写 iPhone 本机应用程序。

My app is accessing web services using JSON. The JSON data we send has nested objects, below is an example of the data served up:

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

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

I'm having problem parsing using the objectForKey and valueForKey NSDictionary methods. I keep getting invalidArgumentException runtime errors.

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

For instance, I want to query the response data for the "authenticationFlag" element.

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

Thanks, Mike Seattle

谢谢,迈克西雅图

回答by jm.

It is hard to tell without some more details (e.g. the JSON parsing code that you are using), but two things strike me as possible:

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

  1. you are not querying with a full path. In the case above, you'd need to first get the enclosing model, the json response, and only then ask the json response dictionary for the authenticationFlag value:

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

  2. perhaps you're using c-strings ("") rather than NSStrings (@"") as keys (although this would likely crash nastily or just not compile). The key should be something than can be cast to id.

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

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

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

While possible, both are probably false, so please include more detail.

虽然可能,但两者都可能是错误的,因此请提供更多详细信息。

回答by breakfreehg

The following is taken directly from Dan Grigsby's Tutorial at - http://mobileorchard.com/tutorial-json-over-http-on-the-iphone/- Please attribute, stealing is bad karma.

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

Fetching JSON Over HTTP

通过 HTTP 获取 JSON

We'll use Cocoa's NSURLConnection to issue an HTTP request and retrieve the JSON data.

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

Cocoa provides both synchronous and asynchronous options for making HTTP requests. Synchronous requests run from the application's main runloop cause the app to halt while it waits for a response. Asynchronous requests use callbacks to avoid blocking and are straightforward to use. We'll use asynchronous requests.

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

First thing we need to do is update our view controller's interface to include an NSMutableData to hold the response data. We declare this in the interface (and not inside a method) because the response comes back serially in pieces that we stitch together rather than in a complete unit.

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

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController {
    IBOutlet UILabel *label;
    NSMutableData *responseData;
}

To keep things simple, we'll kick off the HTTP request from viewDidLoad.

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

Replace the contents of :

替换内容:

#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

This mostly boilerplate code initializes the responseData variable to be ready to hold the data and kicks off the connection in viewDidload; it gathers the pieces as they come in in didReceiveData; and the empty connectionDidFinishLoading stands ready to do something with the results. Using The JSON Data

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

Next, we'll flesh out the connectionDidFinishLoading method to make use of the JSON data retrieved in the last step.

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

Update the connectionDidFinishLoading method :

更新 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;
}

It creates an NSArray. The parser is very flexible and returns objects — including nested objects — that appropriately match JSON datatypes to Objective-C datatypes. Better Error Handling

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

Thus far, we've been using the the convenient, high-level extensions to NSString method of parsing JSON. We've done so with good reason: it's handy to simple send the JSONValue message to a string to accessed to the parsed JSON values.

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

Unfortunately, using this method makes helpful error handling difficult. If the JSON parser fails for any reason it simply returns a nil value. However, if you watch your console log when this happens, you'll see messages describing precisely what caused the parser to fail.

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

It'd be nice to be able to pass those error details along to the user. To do so, we'll switch to the second, object-oriented method, that the JSON SDK supports.

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

Update the connectionDidFinishLoading method in :

更新 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;
    }
}

Using this method gives us a pointer to the error object of the underlying JSON parser that we can use for more useful error handling.

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

Conclusion :

结论 :

The JSON SDK and Cocoa's built-in support for HTTP make adding JSON web services to iPhone apps straightforward.

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

回答by Moheb

    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]]);                
                        }

回答by Brijesh Vadukia

Now, Objective c has introduced in build class for JSON Parsing.

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

 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

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

So utilize this class and make your application error free...:)

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