TouchJSON, работающий с NSNull

Привет Я использую 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:&theError];}

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

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

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

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

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

if(![jsonDataDict objectForKey:someKey])

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

Или я могу просто передать "ноль" в десериализатор?

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

Ответы

Ответ 1

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

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

if (![jsonDataDict objectForKey:someKey])

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

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

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

Ответ 2

Для другой библиотеки 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] значениями и т.п.

Ответ 3

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

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

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