TouchJSON, имеющий дело с NSNull

#objective-c #null #touchjson

#objective-c #null #touchjson

Вопрос:

Привет, я использую TouchJSON для десериализации некоторого JSON. Я использовал его в прошлом, и в тех случаях я имел дело с появлениями NSNull вручную. Я бы подумал, что автору тоже приходилось иметь дело с этим, так что повторное выполнение этого было бы просто накладными расходами. Затем я нашел это в документации:

Избегание значений NSNull в выходных данных.

 NSData *theJSONData = /* some JSON data */
CJSONDeserializer *theDeserializer = [CJSONDeserializer deserializer];
theDeserializer.nullObject = NULL;
NSError *theError = nil;
id theObject = [theDeserializer deserialize:theJSONData error:amp;theError];}
  

Насколько я понимаю, пользователь класса может передать указатель null в стиле C десериализатору, и когда он встретит NSNull, он вставит переданные ему значения (NULL). Поэтому позже, когда я буду использовать значения, я получу не NSNull, а NULL.

Это кажется странным, возвращаемое значение — это NSDictionary, который может содержать только объекты, не должно ли значение по умолчанию быть равно ‘nil’ вместо этого?

Если значение равно NULL, могу ли я проверить значения следующим образом?

 if([jsonDataDict objectForKey:someKey] == NULL)
  

Казалось бы, более логично иметь возможность сделать это:

 if(![jsonDataDict objectForKey:someKey])
  

Нет, чтобы упомянуть все случаи, когда передача nil разрешена, но передача NULL приводит к сбою.

Или я могу просто передать ‘nil’ десериализатору?

Большая часть этого связана с тем, что я все еще борюсь с nil, NULL, [NSNULL null], возможно, я не вижу потенциальных предостережений при использовании nil.

Комментарии:

1. Я прокомментировал ниже, но ради потомства по этому вопросу, NSDictionary не может содержать nil в качестве ключа ИЛИ значения. Из документации Cocoa: «Ни ключ, ни значение не могут быть равны нулю; если вам нужно представить нулевое значение в словаре, вы должны использовать NSNull».

Ответ №1:

Для другой библиотеки JSON, но с теми же проблемами, я создал следующую категорию в NSDictionary:

 @implementation NSDictionary (Utility)

// in case of [NSNull null] values a nil is returned ...
- (id)objectForKeyNotNull:(id)key {
   id object = [self objectForKey:key];
   if (object == [NSNull null])
      return nil;

   return object;
}

@end
  

Всякий раз, когда я имею дело с данными JSON из указанной библиотеки, я извлекаю значения, подобные этому:

 NSString *someString = [jsonDictionary objectForKeyNotNull:@"SomeString"];
  

Таким образом, код в моих проектах становится намного чище, и в то же время мне не нужно думать о работе со значениями [NSNull null] и тому подобным.

Комментарии:

1. Спасибо Вольфгангу. Я вижу необходимость в этой категории, если выбранная вами библиотека JSON не предлагает «NullObject». Это беспорядок, связанный с NSNull каждый раз, когда вам нужно получить доступ к вашему объекту модели 15 свойств 🙂

2. Это хороший способ сделать это (и фактически то, как я делаю это в своих собственных приложениях). Преимущество этого заключается в том, что вы все еще можете проверить, существует ли ключ в словаре с нулевым значением; когда для TouchJSON nullObject установлено значение nil, вы не можете отличить нулевое значение от отсутствующего ключа.

3. Кодирование значений ключа будет преобразовываться между NSNull и nil в коллекциях для вас. developer.apple.com/library/ios/documentation/Cocoa/Conceptual /…

Ответ №2:

nil и NULL фактически оба равны нулю, поэтому на практике они взаимозаменяемы. Но вы правы, для обеспечения согласованности в документации для TouchJSON следовало использовать theDeserializer.nullObject = nil вместо NULL .

Теперь, когда вы это делаете, ваш второй предикат действительно работает нормально:

 if (![jsonDataDict objectForKey:someKey])
  

потому что TouchJSON опускает ключ из словаря, когда вы nullObject установили значение nil (или NULL ). Когда ключ не существует в словаре, NSDictionary возвращает nil, который равен нулю, поэтому ваше условие if работает так, как вы ожидаете.

Если вы не указали nullObject as nil , вы можете вместо этого проверить наличие null следующим образом:

 if ([jsonDataDict objectForKey:someKey] == [NSNull null])
  

Комментарии:

1. Спасибо, это отлично отвечает на этот вопрос, пока я могу последовательно ожидать, что будет возвращено нулевое значение, все будет в порядке.

Ответ №3:

Существуют библиотеки, которые имеют дело с этим. Одним из них является SwiftyJSON в Swift, другим является NSTEasyJSON в Objective-C. С помощью этой библиотеки (NSTEasyJSON) будет легко справиться с такими проблемами. В вашем случае вы можете просто проверить нужные вам значения:

 NSTEasyJSON *JSON = [NSTEasyJSON withData:JSONData];
NSString *someValue = JSON[someKey].string;
  

Это значение будет NSString или nil , и вам не следует самостоятельно проверять его на наличие NSNull, NULL.