Comprobación de un valor nulo en Objective-C que se ha devuelto desde una cadena JSON

78

Tengo un objeto JSON que proviene de un servidor web.

El registro es algo como esto:

{          
   "status":"success",
   "UserID":15,
   "Name":"John",
   "DisplayName":"John",
   "Surname":"Smith",
   "Email":"email",
   "Telephone":null,
   "FullAccount":"true"
}

Tenga en cuenta que el teléfono entra como nulo si el usuario no ingresa uno.

Al asignar este valor a a NSString, en el NSLogaparece como<null>

Estoy asignando la cadena así:

NSString *tel = [jsonDictionary valueForKey:@"Telephone"];

¿Cuál es la forma correcta de verificar este <null>valor? Me impide salvar un NSDictionary.

He intentado usar las condiciones [myString length]y myString == nilymyString == NULL

Además, ¿cuál es el mejor lugar en la documentación de iOS para leer sobre esto?

Chris
fuente

Respuestas:

189

<null>así es como se registra el singleton de NSNull. Entonces:

if (tel == (id)[NSNull null]) {
    // tel is null
}

(El singleton existe porque no puede agregar nila clases de colección).

Wevah
fuente
41
Si quieres hacerlo sin el elenco, también puedes probar:if ([tel isKindOfClass:[NSNull class]])
Aaron Hayman
podemos usar: if (object isEqual: [NSNull null]) {--logic here--}
Gajendra K Chauhan
24

Aquí está el ejemplo con el elenco:

if (tel == (NSString *)[NSNull null])
{
   // do logic here
}
Pulga
fuente
o if (tel == (NSString *) NSNull.null) {// hacer lógica aquí}
Raphael Oliveira
10

También puede verificar esta Cadena entrante de esta manera también: -

if(tel==(id) [NSNull null] || [tel length]==0 || [tel isEqualToString:@""])
{
    NSlog(@"Print check log");
}
else
{  

    NSlog(@Printcheck log %@",tel);  

}
Nitin Gohel
fuente
Su primera NSLoglínea es incorrecta ... debería decir que la cadena está vacía. ¿Y por qué lo imprimirías en ese caso?
bdesham
gracias por el consejo e NSLog
imprimo
9

Si se trata de una API "inestable", es posible que desee recorrer todas las claves para comprobar si son nulas. Creé una categoría para lidiar con esto:

@interface NSDictionary (Safe)
-(NSDictionary *)removeNullValues;
@end

@implementation NSDictionary (Safe)

-(NSDictionary *)removeNullValues
{
    NSMutableDictionary *mutDictionary = [self mutableCopy];
    NSMutableArray *keysToDelete = [NSMutableArray array];
    [mutDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        if (obj == [NSNull null]) 
        {
            [keysToDelete addObject:key];
        }
    }];
    [mutDictinary removeObjectsForKeys:keysToDelete];
    return [mutDictinary copy];
}
@end
Kyle C
fuente
4

La mejor respuesta es la que ha comentado Aaron Hayman a continuación de la respuesta aceptada:

if ([tel isKindOfClass:[NSNull class]])

No produce una advertencia :)

kjoelbro
fuente
3

si tiene muchos atributos en json, usar la ifdeclaración para verificarlos uno por uno es problemático. Lo que es aún peor es que el código sería feo y difícil de mantener.

Creo que el mejor enfoque es crear una categoría de NSDictionary:

// NSDictionary+AwesomeDictionary.h

#import <Foundation/Foundation.h>

@interface NSDictionary (AwesomeDictionary)
- (id)validatedValueForKey:(NSString *)key;
@end

// NSDictionary+AwesomeDictionary.m

#import "NSDictionary+AwesomeDictionary.h"

@implementation NSDictionary (AwesomeDictionary)
- (id)validatedValueForKey:(NSString *)key {
    id value = [self valueForKey:key];
    if (value == [NSNull null]) {
        value = nil;
    }
    return value;
}
@end

después de importar esta categoría, puede:

[json validatedValueForKey:key];
Brian
fuente
2

Normalmente lo hago así:

Supongo que tengo un modelo de datos para el usuario y tiene una propiedad NSString llamada correo electrónico, obtenida de un dictado JSON. Si el campo de correo electrónico se utiliza dentro de la aplicación, convertirlo en una cadena vacía evita posibles bloqueos:

- (id)initWithJSONDictionary:(NSDictionary *)dictionary{

    //Initializer, other properties etc...

    id usersmail = [[dictionary objectForKey:@"email"] copy];
    _email = ( usersmail && usersmail != (id)[NSNull null] )? [usersmail copy] : [[NSString      alloc]initWithString:@""];
}
Yunus Nedim Mehel
fuente
2

En Swift puedes hacer:

let value: AnyObject? = xyz.objectForKey("xyz")    
if value as NSObject == NSNull() {
    // value is null
    }
Segev
fuente
La pregunta es sobre Objective-C, no Swift.
JasonMArcher
4
@JasonMArcher La respuesta todavía proporciona algún valor para aquellos que llegan a la pregunta desde una búsqueda en Google. Después de todo, es una pregunta de 4 años.
Beau Nouvelle
0

Lo mejor sería seguir las mejores prácticas, es decir, utilizar un modelo de datos real para leer datos JSON.

Eche un vistazo a JSONModel: es fácil de usar y convertirá [NSNUll null] a valores * nil * automáticamente, por lo que podría hacer sus comprobaciones como de costumbre en Obj-c como:

if (mymodel.Telephone==nil) {
  //telephone number was not provided, do something here 
}

Eche un vistazo a la página de JSONModel: http://www.jsonmodel.com

Aquí también hay un recorrido sencillo para crear una aplicación basada en JSON: http://www.touch-code-magazine.com/how-to-make-a-youtube-app-using-mgbox-and-jsonmodel/

Marin Todorov
fuente
¿Ese sitio JSONModel todavía existe? No está en inglés, así que no puedo estar seguro, pero no parece que tenga mucho que ver con JSON.
Stewart Macdonald
0

Intenté mucho método, pero nada funcionó. Finalmente esto funcionó para mí.

NSString *usernameValue = [NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults] valueForKey:@"usernameKey"]];

if ([usernameValue isEqual:@"(null)"])
{
     // str is null
}

fuente
0
if([tel isEqual:[NSNull null]])
{
   //do something when value is null
}
Gajendra K Chauhan
fuente
Genera una advertencia: tipos de punteros incompatibles que envían 'NSNull * _Nonnull' al parámetro de tipo 'Class'
Adnan Asghar
0

Prueba esto:

if (tel == (NSString *)[NSNull null] || tel.length==0)
{
    // do logic here
}
Mritunjay
fuente
0

Yo uso esto:

#define NULL_TO_NIL(obj) ({ __typeof__ (obj) __obj = (obj); __obj == [NSNull null] ? nil : obj; }) 
Carles Estevadeordal
fuente
0

si obtenemos un valor nulo como, entonces podemos verificarlo con el siguiente fragmento de código.

 if(![[dictTripData objectForKey:@"mob_no"] isKindOfClass:[NSNull class]])
      strPsngrMobileNo = [dictTripData objectForKey:@"mobile_number"];
  else
           strPsngrMobileNo = @"";
Chandni - Systematix
fuente
-6

Aquí también puede hacerlo verificando la longitud de la cadena, es decir,

if(tel.length==0)
{
    //do some logic here
}
Rahul Narang
fuente
3
No, si teles una instancia de NSNull, esto generará una excepción.
Kurt Revis
sí, creo que tendremos que verificar que sea nulo o no también. Tenemos que considerar las condiciones anteriores también
Rahul Narang