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?

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


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
}

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);  

}

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

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 :)


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];

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:@""];
}

2

En Swift puedes hacer:

let value: AnyObject? = xyz.objectForKey("xyz")    
if value as NSObject == NSNull() {
    // value is null
    }

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/


¿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
}

0
if([tel isEqual:[NSNull null]])
{
   //do something when value is null
}

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
}

0

Yo uso esto:

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

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 = @"";

-6

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

if(tel.length==0)
{
    //do some logic here
}

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.