Разбор JSON с использованием NSJSONSerialization в iOS

Я разбираю JSON в своем коде. Но я получаю некоторые неожиданные проблемы при получении данных проанализированного JSON. Итак, позвольте мне объяснить мою проблему.

Мне нужно проанализировать следующие данные JSON с помощью xcode. Вот как выглядят данные для анализа, когда я нажимаю тот же URL-адрес в браузере:

{
"RESPONSE":[
    {"id":"20",
    "username":"john",
    "email":"[email protected]",
    "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];

Если я печатаю объект json, используя NSLog, то есть NSLog(@"json: %@", [json description]);, это выглядит так:

json: {
    MESSAGE = "Here will be message";
    RESPONSE =(
                {
            email = "[email protected]";
            id = 20;
            location = "31.000,71.000";
            phone = 1234567890;
            username = john;
        }
    );
    STATUS = OK;
}

Итак, здесь я заметил две вещи:

  1. Последовательность ключей (или узлов) (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:(
    [email protected]
)

Итак, мой вопрос: почему это не выглядит как обычная строка? Если бы я попытался использовать эти переменные дальше, они бы показали значение, заключенное в фигурные скобки '(' & ')'. Это происходит из-за NSJSONSerialization?


person Nayan    schedule 05.12.2013    source источник
comment
Форматирование изменено, потому что теперь это NSDictionary вместо форматированной строки JSON. NSDictionary имеет собственный формат для печати своего описания   -  person NeverBe    schedule 05.12.2013


Ответы (6)


Прежде всего, в вашем JSON ответе dictionary под ключом 'RESPONSE' у вас есть массив, а не dictionary, и этот массив содержит dictionary объект. Итак, чтобы извлечь имя пользователя и идентификатор электронной почты, как показано ниже

NSMutableDictionary *response = [[[json valueForKey:@"RESPONSE"] objectAtIndex:0]mutableCopy];
 NSString *username = [response valueForKey:@"username"];
 NSString *emailId = [response valueForKey:@"email"];
person Suryakant Sharma    schedule 05.12.2013
comment
[[json valueForKey:@"RESPONSE"] objectAtIndex:0]; нельзя изменить, если вы не запросите mutableCopy следующим образом: [[[json valueForKey:@"RESPONSE"] objectAtIndex:0] mutableCopy]; - person neilco; 05.12.2013

Когда вы видите такие фигурные скобки, они представляют собой массив, а не словарь. Ваш JSON также показывает это, заключая данные в скобки («[» и «]»). Так:

RESPONSE =(
                {
            email = "[email protected]";
            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]);

чтобы увидеть, что возвращается из словаря.

person Chris    schedule 05.12.2013

1) Последовательность ключей (или узлов) (СООБЩЕНИЕ, ОТВЕТ и СТАТУС) изменена по сравнению с веб-ответом выше.

NSLog из NSDictionary основано на отсортированных ключах.

2) ОТВЕТ заключен в фигурные скобки «(» и «)».

RESPONSE =(
            {
        email = "[email protected]";
        id = 20;
        location = "31.000,71.000";
        phone = 1234567890;
        username = john;
    }
);

RESPONSE — это ключ, а значение — NSArray. Массив содержит один объект NSDictionary с такими ключами, как электронная почта, идентификатор, местоположение, телефон и имя пользователя.

ПРИМЕЧАНИЕ: () говорит о массиве. {} говорит словарь.

person Anoop Vaidya    schedule 05.12.2013
comment
эй, спасибо, братан, за разъяснение моей теоретической концепции. Следовательно +1, но ответ суряканта у меня сработал практически. - person Nayan; 05.12.2013

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 );
person Midhun MP    schedule 05.12.2013
comment
[json valueForKey:@"RESPONSE"]; нельзя изменить, если вы не запросите mutableCopy следующим образом: [[json valueForKey:@"RESPONSE"] mutableCopy]; - person neilco; 05.12.2013
comment
@neilco: я только что увидел ваш комментарий (через 3 года). Можете ли вы сказать мне, каково значение mutableCopy в этом контексте? - person Midhun MP; 23.03.2017
comment
@midhun: В своем ответе вы указали: NSMutableArray *response = [json valueForKey:@"RESPONSE"];, но valueForKey: возвращает только неизменяемые объекты, поэтому response на самом деле является экземпляром NSArray, а не NSMutableArray. Если вы хотите, чтобы response было изменяемым, вам нужно вызвать mutableCopy для возвращаемого значения valueForKey:. - person neilco; 23.03.2017

знак прагмы — проверка достижимости и анализ данных

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

отметка прагмы - делегат 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;
 }

#импорт.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;
person Mithun R    schedule 03.05.2017
comment
Отвечать только кодами - не очень хороший ответ. Пожалуйста, прочтите это как ответить, чтобы получить качественный ответ. - person thewaywewere; 03.05.2017

Сериализируя данные, вы получаете объект json. Объект Json и словарь немного отличаются.

Вместо того, чтобы использовать:

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

использовать:

NSDictionary    *json    =   (NSDictionary*) data;
person Shob-Z    schedule 05.12.2013
comment
Это вообще не отвечает на вопрос. JSONObjectWithData:options:error: принимает представление NSData строки JSON и десериализует его либо в NSArray, либо в NSDictionary. - person neilco; 05.12.2013
comment
Объект JSON и NSDictionary эквивалентны. Документация JSON называет его объектом, но документация JSON применима ко всем реализациям, а не только к iOS. В iOS массивы хранятся как NSArray*, объекты хранятся как NSDictionary*, строки как NSString*, bool, integer и number как NSNumber*. А приведение данных типа NSData* к NSDictionary* не принесет ничего полезного. - person gnasher729; 11.03.2014