【问题标题】:JSON parsing using NSJSONSerialization in iOS在 iOS 中使用 NSJSONSerialization 解析 JSON
【发布时间】:2013-12-22 08:09:12
【问题描述】:

我在我的代码中解析JSON。但是在检索已解析的JSON 的数据时,我遇到了一些意想不到的问题。所以让我解释一下我的问题。

我必须使用 xcode 解析以下 JSON 数据。这是我在浏览器中点击相同 URL 时要解析的数据的样子:

{
"RESPONSE":[
    {"id":"20",
    "username":"john",
    "email":"abc@gmail.com",
    "phone":"1234567890",
    "location":"31.000,71.000"}],
"STATUS":"OK",
"MESSAGE":"Here will be message"
}

我获取此JSON 数据的代码如下:

NSData *data = [NSData dataWithContentsOfURL:finalurl];
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];

如果我使用NSLog 打印对象json,即NSLog(@"json: %@", [json description]);,它看起来像:

json: {
    MESSAGE = "Here will be message";
    RESPONSE =(
                {
            email = "abc@gmail.com";
            id = 20;
            location = "31.000,71.000";
            phone = 1234567890;
            username = john;
        }
    );
    STATUS = OK;
}

所以,在这里我观察到两件事:

  1. 与上面的 Web 响应相比,键(或节点)(MESSAGE、RESPONSE 和 STATUS)的序列发生了变化。

  2. RESPONSE 括在 '(' & ')' 大括号中。

现在,如果我将键 MESSAGE 和 STATUS 和 NsLog 的值分开,那么它们将被打印为正确的字符串。

点赞msgStr:Here will be message & Status:OK

但是如果我将 RESPONSE 的值分离为字典,然后再次分离该字典的子值,例如 email 和 username,那么 我无法得到这些作为字符串。

这是我目前写的代码:

NSMutableDictionary *response = [json valueForKey:@"RESPONSE"];
NSString *username = [response valueForKey:@"username"];
NSString *emailId = [response valueForKey:@"email"];

如果我打印username 和emailId,那么它们不会作为普通字符串打印,而是输出为:

username:(
    john
)

email:(
    abc@gmail.com
)

所以我的问题是为什么它没有像普通字符串一样?如果我尝试进一步使用这些变量,那么它们会显示包含在 '(' & ')' 大括号内的值。这是因为NSJSONSerialization吗?

【问题讨论】:

  • 格式已更改,因为现在它是 NSDictionary 而不是格式化的 JSON 字符串。 NSDictionary 有自己的格式来打印它的描述

标签: ios objective-c json parsing nsjsonserialization


【解决方案1】:

当你看到这样的大括号时,它代表一个数组,而不是字典。您的 JSON 还通过将数据括在括号(“[”和“]”)中来显示这一点。所以:

RESPONSE =(
                {
            email = "abc@gmail.com";
            id = 20;
            location = "31.000,71.000";
            phone = 1234567890;
            username = john;
        }
);

RESPONSE 是一个字典数组。要访问数据,请遍历数组:

for (NSDictionary *responseDictionary in [JSONDictionary objectForKey:@"RESPONSE"]) {
        NSString *name = [responseDictionary objectForKey:@"username"];
        .....
}

或在索引处获取字典:

NSDictionary *responseDictionary = [[JSONDictionary objectForKey:@"RESPONSE"] objectAtIndex:0];
NSString *name = [responseDictionary objectForKey:@"username"];

如有疑问,请记录课程:

NSLog(@"%@", [[dictionary objectForKey:@"key"] class]);

查看字典返回的内容。

【讨论】:

    【解决方案2】:

    RESPONSE 包含一个数组而不是一个对象。

    所以试试这样:

    NSMutableArray *response = [json valueForKey:@"RESPONSE"];
    NSString *username = [[response objectAtIndex:0] valueForKey:@"username"];
    NSString *emailId  = [[response objectAtIndex:0] valueForKey:@"email"];
    NSLog(@"User=>[%@] Pwd=>[%@]",username ,emailId );
    

    【讨论】:

    • [json valueForKey:@"RESPONSE"]; 是不可变的,除非您像这样请求mutableCopy:[[json valueForKey:@"RESPONSE"] mutableCopy];
    • @neilco:我刚刚看到你的评论(3 年后)。你能告诉我mutableCopy 在这种情况下的重要性吗?
    • @midhun:在您的回答中,您指定:NSMutableArray *response = [json valueForKey:@"RESPONSE"]; 但valueForKey: 仅返回不可变对象,因此response 实际上是NSArray 的实例,而不是NSMutableArray。如果你想让response可变,你需要在valueForKey:的返回值上调用mutableCopy。
    【解决方案3】:

    首先在您的JSON 响应dictionary 中,在键“RESPONSE”下,您有一个不是dictionary 的数组,并且该数组包含dictionary 对象。 所以要提取 username 和 email ID 如下

    NSMutableDictionary *response = [[[json valueForKey:@"RESPONSE"] objectAtIndex:0]mutableCopy];
     NSString *username = [response valueForKey:@"username"];
     NSString *emailId = [response valueForKey:@"email"];
    

    【讨论】:

    • [[json valueForKey:@"RESPONSE"] objectAtIndex:0]; 是不可变的,除非您像这样请求mutableCopy:[[[json valueForKey:@"RESPONSE"] objectAtIndex:0] mutableCopy];
    【解决方案4】:

    通过序列化数据,你得到一个 json 对象。 Json 对象和字典有点不同。

    而不是使用:

    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
    

    使用:

    NSDictionary    *json    =   (NSDictionary*) data;
    

    【讨论】:

    • 这根本没有回答问题。 JSONObjectWithData:options:error: 采用 JSON 字符串的 NSData 表示并将其反序列化为 NSArray 或 NSDictionary。
    • JSON 对象和 NSDictionary 是等价的。 JSON 文档将其称为“对象”,但 JSON 文档适用于所有实现,而不仅仅是 iOS 实现。在 iOS 中,“数组”存储为 NSArray*,“对象”存储为 NSDictionary*,“字符串”存储为 NSString*,bool、整数和数字存储为 NSNumber*。将类型为 NSData* 的数据转换为 NSDictionary* 不会有任何用处。
    【解决方案5】:

    1) 键(或节点)(MESSAGE、RESPONSE 和 STATUS)的序列是 与上面的网络响应相比发生了变化。

    NSDictionary 的 NSLog 是基于排序的键。

    2) RESPONSE 包含在“(' & ')' 大括号中。

    RESPONSE =(
                {
            email = "abc@gmail.com";
            id = 20;
            location = "31.000,71.000";
            phone = 1234567890;
            username = john;
        }
    );
    

    RESPONSE 是键,值是 NSArray。该数组包含一个NSDictionary 对象,其键为电子邮件、ID、位置、电话和用户名。

    注意: () 表示数组。 {} 表示字典。

    【讨论】:

    • 嘿,谢谢兄弟,澄清了我的理论概念。因此 +1,但 suryakant 的回答实际上对我有用。
    【解决方案6】:

    pragma mark - 检查可达性和解析数据

    NSString *urlString = [NSString stringWithFormat: @"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=11.021459,76.916332&radius=2000&types=atm&sensor=false&key=AIzaSyD7c1IID7zDCdcfpC69fC7CUqLjz50mcls"];
    NSURL *url = [NSURL URLWithString: urlString];
    NSData *data = [NSData dataWithContentsOfURL:url];
    NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData: data options: 0 error: nil];
    array = [[NSMutableArray alloc]init];
    array = [[jsonData objectForKey:@"results"] mutableCopy];
    [jsonTableview reloadData];}
    

    pragma mark- UITableView 委托

      - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    
    return 1;
     }
    
     - (NSInteger)tableView:(UITableView *)tableView          
     numberOfRowsInSection:(NSInteger)section {
    
    return array.count;
      }
    
     - (UITableViewCell *)tableView:(UITableView *)tableView    
     cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
      static NSString *cellid = @"cell";
    UITableViewCell *cell = [tableView       
     dequeueReusableCellWithIdentifier:cellid];
    cell = [[UITableViewCell   
     alloc]initWithStyle:UITableViewCellStyleSubtitle    
      reuseIdentifier:cellid];
    
    cell.textLabel.text = [[array    
     valueForKeyPath:@"name"]objectAtIndex:indexPath.row];
    cell.detailTextLabel.text = [[array 
    valueForKeyPath:@"vicinity"]objectAtIndex:indexPath.row];
    NSURL *imgUrl = [NSURL URLWithString:[[array 
    valueForKey:@"icon"]objectAtIndex:indexPath.row]];
    NSData *imgData = [NSData dataWithContentsOfURL:imgUrl];
    cell.imageView.layer.cornerRadius =        
     cell.imageView.frame.size.width/2;
    cell.imageView.layer.masksToBounds = YES;
    cell.imageView.image = [UIImage imageWithData:imgData];
    
    return cell;
     }
    

    #import.h

    @interface JsonViewController :     
    UIViewController<UITableViewDelegate,UITableViewDataSource>
    @property (weak, nonatomic) IBOutlet UITableView *jsonTableview;
    @property (weak, nonatomic) IBOutlet UIBarButtonItem *barButton;
    @property (strong,nonatomic)NSArray *array;
    @property NSInteger select;
    

    【讨论】:

    • 只用代码回答不好。请阅读此how-to-answer 以提供高质量的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-20
    相关资源
    最近更新 更多