NSDictionary objectForKey возвращаемое значение - PullRequest
2 голосов
/ 22 июня 2009

Я использую json-framework для создания NSDictionary из ответа JSON. Это прекрасно работает.

Теперь внутри этой полезной нагрузки JSON находятся один или несколько объектов - давайте назовем их X. В XML это примерно так:

<OBJECTS>
  <X>
    ...
  </x>
  <X>
    ...
  </X>
  <X>
    ...
  </X>
</OBJECTS>

Когда я смотрю в вышеупомянутом объекте NSDictionary для всех X, вот так:

NSDictionary *results = [[dict objectForKey:@"OBJECTS"] objectForKey:@"X"];

Или даже:

NSDictionary *results = [dict valueForKeyPath:@"OBJECTS.X"];

Я получаю, согласно gdb, NSCFArray объектов NSDictionary. (Да, я тоже чувствую здесь что-то смешное, но об этом чуть позже.)

Когда есть только один объект с именем X, я получаю обратно добросовестный NSDictionary.

Итак ... что я должен сделать, чтобы заставить это вести себя последовательно, независимо от того, сколько есть X?

На первый взгляд, я думаю, что я просто изменил бы результаты на NSArray *, но что произойдет, если я хочу быстро перечислить результаты? Прямо сейчас я делаю это:

for (NSDictionary *result in results)

В случае NSCFArray (несколько X) я возвращаю отдельный NSDictionary для каждого X. В одном случае X я возвращаю один NSDictionary, за исключением того, что теперь моя перспектива на один уровень слишком глубока. Другими словами, вместо этого (надуманный пример):

(gdb) po results
<NSCFArray 0xd4a940>(
{
    foo =     {
        bar = "something";
    };
}
{
    foo =     {
        bar = "something else";
    };
}
)

Я получаю это:

(gdb) po results
{
    foo =     {
        bar = "something";
    };
}

Подсказки приветствуются / приветствуются! Вы можете даже спросить, нужно ли вообще разбивать это на части, но сейчас давайте предположим, что это путешествие действительно необходимо. (Тем не менее, я рад, что меня убедили иначе, если кто-то чувствует себя достаточно сильно об этом.)

В конце концов, я хочу получить NSArray объектов NSDictionary.

Ответы [ 4 ]

2 голосов
/ 24 февраля 2010
NSDictionary *results = [[dict objectForKey:@"OBJECTS"] objectForKey:@"X"];

и

NSDictionary *results = [dict valueForKeyPath:@"OBJECTS.X"];

Вышеуказанные два абсолютно одинаковы. Первая операция немного дороже, чем вторая.

1 голос
/ 22 июня 2009

Я не знаком с JSON или json-framework, но очевидно, что objectForKey нельзя использовать для доступа к X, поскольку все они имеют одинаковый ключ.

Если вы знаете, что objectForKey: @ "OBJECTS" вернет либо NSDictionary (один элемент), либо NSArray NSDictionarys (несколько элементов X), то вы можете сделать что-то вроде:

if ( ![results isKindOfClass:[NSArray class]] ) {
    results =[NSArray arrayWithObject:results];
}

Это даст вам последовательный результат, если вы точно поймете, как будет вести себя json-framework. Это будет несколько хрупко, если элементы когда-либо возвращают массив записей вместо NSDitionary, то все это развалится.

Может быть параметр конфигурации для json-framework, который позволяет вам контролировать его поведение в этом случае, и это было бы предпочтительным.

0 голосов
/ 23 июня 2009

Я не думаю, что ваши два примера кода

NSDictionary *results = [[dict objectForKey:@"OBJECTS"] objectForKey:@"X"];

и

NSDictionary *results = [dict valueForKeyPath:@"OBJECTS.X"];

эквивалентны.Key-Value-Coding имеет несколько дополнительных возможностей для работы с коллекциями, которые могут вас оттолкнуть.(Пример можно найти в сообщении блога Theocacao: NSArray и KVC Скотта Стивенсона.) Если вы вернетесь к прежнему, вы можете получить ожидаемое поведение.

0 голосов
/ 22 июня 2009

Вот что я в итоге сделал:

// Get the JSON response and return the result:
NSString *jsonString = [NSString stringWithContentsOfURL:url];
NSDictionary *dict = [jsonString JSONValue];

// If OBJECTS.X gets a dictionary (one value), make an array of one.
id myObject = [dict valueForKeyPath:@"OBJECTS.X"];
if ([myObject isKindOfClass:[NSDictionary class]]) {
    results = [NSArray arrayWithObject:myObject];
} else {
    results = myObject;
}

Стоит отметить, что JSONValue также может возвращать словарь или массив. Тем не менее, я заглядываю в словарь пост-назначения (OBJECTS.X).

...