Вопрос

Я использую 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, НСКФАррай объектов NSDictionary.(Да, я тоже чувствую здесь что-то забавное, но об этом чуть позже.)

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

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

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

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.

Это было полезно?

Решение

Я не знаком с 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, который позволяет вам контролировать его поведение в этом случае, и это будет предпочтительнее.

Другие советы

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

и

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

Два вышеперечисленных абсолютно одинаковы.Первая операция немного дороже второй.

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

// 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).

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

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

и

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top