如何检测字典是否为空或 null

How to detect if a dictionary is empty or null

我收到一个 JSON 字符串,我需要对其进行迭代以检索一些 object 值。 这是结构

-meta
-objects
   |_cabdriver
              |_employee
   |client

objects树下有objects,还有child个节点,比如cabdriver和client。 child 节点 cabdriver 还有另一个 child 节点称为 employee。

这是我迭代它的方式:

NSArray *messageArray = [json objectForKey:@"objects"];
historialServicios = [[NSMutableArray alloc]init];

// Parse and loop through the JSON
for (dictionary in messageArray) {
    //datos de nivel objects
    NSString * date = [dictionary objectForKey:@"date"];
    NSString * origin = [dictionary objectForKey:@"origin"];
    NSString * destiny = [dictionary objectForKey:@"destiny"];
    NSString * rate = [dictionary objectForKey:@"service_rate"];
    NSString * state = [dictionary objectForKey:@"state"];
    NSString * time_service = [dictionary objectForKey:@"time_service"];
    NSString * id_service = [dictionary objectForKey:@"id"];

    //datos de nivel cliente
    NSDictionary *level2Dict = [dictionary objectForKey:@"client"];
    NSString *client_id = [level2Dict objectForKey:@"id"];

    //datos de nivel cabdriver
    NSDictionary *cabdriverLevelDict=[dictionary objectForKey:@"cabdriver"];

    //datos de nivel employee
    NSDictionary *employeeLevelDict = [cabdriverLevelDict objectForKey:@"employee"];

    //datos del employee
    NSString *driverName = [employeeLevelDict objectForKey:@"name"];
    NSString *driverLastname = [employeeLevelDict objectForKey:@"lastname"];
    NSString *driverPhone = [employeeLevelDict objectForKey:@"phone"];
    NSString *driverId = [employeeLevelDict objectForKey:@"id"];

    [historialServicios addObject:@{
                                   @"time_service": time_service,
                                   @"id_service": id_service,
                                   @"rate": rate,
                                   @"destiny": destiny,
                                   @"state": state,
                                   @"origin": origin,
                                   @"client_id":client_id,
                                   @"date": date,
                                   @"driverName":driverName,
                                   @"driverLastname": driverLastname,
                                   @"driverPhone": driverPhone,
                                   @"driverId": driverId

                                   }];
    NSLog(@"DESPUES DE ANADIR OBJETOS");
    NSLog(@"OBJETO ANADIDO==>TIME SERVICE = %@, ID SERVICE=%@, SERVICE RATE=%@,SERVICE DATE=%@,DESTINY=%@, STATE =%@,CLIENT ID=%@, ORIGIN=%@,DRIVER NAME=%@, DRIVER LASTNAME=%@,DRIVER PHONE=%@, DRIVER ID=%@",time_service,id_service,rate,date,destiny,state,client_id,origin,driverName,driverLastname,driverPhone,driverId);

    //insertamos objetos en diccionario historialServicios
}

如果 object 有所有节点,一切正常,但有时,节点出租车司机是空的,没有雇员 child 节点。如果是这种情况,我会抛出异常并且应用程序崩溃。

如何判断节点员工不存在,避免出现异常?

谢谢。

检查字典的计数

if ([cabdriverLevelDict count] == 0) {
 NSLog("empty");
}
else{
 // Do your stuff !!
}

你可以试试

NSDictionary *employeeLevelDict = [cabdriverLevelDict objectForKey:@"employee"];


if (employeeLevelDict.count != 0)
{             
     // do something if dict is not empty
}
else
{

}];

在这里试试这个:

if( cabdriverLevelDict.allkeys.count ){
    // Do something with the dict
} else {
    // dict is empty
}
if (![cabdriverLevelDict isKindOfClass:[NSNull class]] ){
    //do something
}

试试这个

您可以声明一个类别来处理注入到您的 json 中的 [NSNull null] 值。

@interface NSDictionary (NilNull)
- (id)optionalObjectForKey:(id)key;
- (id)optionalObjectForKey:(id)key defaultValue:(id)defaultValue;
@end

@implementation NSDictionary (NilNull)
- (id)optionalObjectForKey:(id)key {
  return [self optionalObjectForKey:key defaultValue:nil];
]
- (id)optionalObjectForKey:(id)key defaultValue:(id)defaultValue {
  id obj = [self objectForKey:key];
  return (obj == [NSNull null] || !obj) ? defaultValue : obj;
}
@end

然后改用它:

NSDictionary *cabdriverLevelDict = [dictionary optionalObjectForKey:@"cabdriver"];
NSDictionary *employeeLevelDict = [cabdriverLevelDict optionalObjectForKey:@"employee"];

您尚未发布异常的内容,但从外观上看,它可能与尝试向新词典添加 nil 值有关。

然后对所有生成对象的数据查找使用默认值 [NSNull null],您将使用这些对象构建最终字典。完整的查找源现在是这样的:

NSString * date = [dictionary optionalObjectForKey:@"date" defaultValue:[NSNull null]];
NSString * origin = [dictionary optionalObjectForKey:@"origin" defaultValue:[NSNull null]];
NSString * destiny = [dictionary optionalObjectForKey:@"destiny" defaultValue:[NSNull null]];
NSString * rate = [dictionary optionalObjectForKey:@"service_rate" defaultValue:[NSNull null]];
NSString * state = [dictionary optionalObjectForKey:@"state" defaultValue:[NSNull null]];
NSString * time_service = [dictionary optionalObjectForKey:@"time_service" defaultValue:[NSNull null]];
NSString * id_service = [dictionary optionalObjectForKey:@"id" defaultValue:[NSNull null]];

//datos de nivel cliente
NSDictionary *level2Dict = [dictionary optionalObjectForKey:@"client" defaultValue:[NSDictionary dictionary]];
NSString *client_id = [level2Dict optionalObjectForKey:@"id" defaultValue:[NSNull null]];

//datos de nivel cabdriver
NSDictionary *cabdriverLevelDict=[dictionary optionalObjectForKey:@"cabdriver" defaultValue:[NSDictionary dictionary]];

//datos de nivel employee
NSDictionary *employeeLevelDict = [cabdriverLevelDict optionalObjectForKey:@"employee" defaultValue:[NSDictionary dictionary]];

//datos del employee
NSString *driverName = [employeeLevelDict optionalObjectForKey:@"name" defaultValue:[NSNull null]];
NSString *driverLastname = [employeeLevelDict optionalObjectForKey:@"lastname" defaultValue:[NSNull null]];
NSString *driverPhone = [employeeLevelDict optionalObjectForKey:@"phone" defaultValue:[NSNull null]];
NSString *driverId = [employeeLevelDict optionalObjectForKey:@"id" defaultValue:[NSNull null]];

基本上,您需要检查获得的每一个结果。如果您不这样做,您的应用程序就会受到攻击,一次攻击可能会让黑客进入用户的设备并造成无限的损害。在你期望字典的地方,你可能会得到 nil,你可能会得到 null,你可能会得到一个数字或一个字符串,任何东西。这很简单。

NSDictionary* dict = ...; 
if (! [dict isKindOfClass:[NSDictionary class]]) dict = nil;

在Objective-C中,nil对象是相当安全的。例如,您可以使用 objectForKey [@"employee"],结果将是 nil。无论如何你都可能收到零。

只检查 [NSNull null] 是没有意义的,因为服务器给你的任何其他结果都会让你的应用程序崩溃。只需检查您实际期望的内容。丢弃不正确的数据很好,毕竟 JSON 反序列化器将丢弃所有数据,如果只有一个字节的数据是错误的。

有时您需要多加注意,因为服务器行为不当而您必须应对。例如,服务器应该 return 字典数组可能只给你一个字典,如果只有一个,所以你会检查例如

NSArray* arrayOfDicts = ...;
if ([arrayOfDicts isKindOfClass:[NSDictionary class]] arrayOfDicts = @[arrayOfDicts];
else if (! [arrayOfDicts isKindOfClass:[NSArray class]] arrayOfDicts = nil;

正如其他人指出的那样,如果传递到字典中的任何对象为 nil,则会引发异常,使您的应用程序崩溃。通过执行以下操作:

 [historialServicios addObject:@{
                               @"time_service": time_service,
                               @"id_service": id_service,
                               @"rate": rate,
                               @"destiny": destiny,
                               @"state": state,
                               @"origin": origin,
                               @"client_id":client_id,
                               @"date": date,
                               @"driverName":driverName,
                               @"driverLastname": driverLastname,
                               @"driverPhone": driverPhone,
                               @"driverId": driverId

                               }];

您依赖所有这些对象(例如 time_service、id_service 等)不为零。正如您所指出的,它们可以为零,因此您需要有一种方法来检查您所做的每个对象。我建议使用 NSMutableDictionary,制作一个类别方法,如果它们都不为零,则只添加 key/value 对:

@implementation NSMutableDictionary (Util)

-(void)setObjectOrRemoveIfNil:(id)anObject forKey:(id<NSCopying>)aKey
{
    if (anObject == nil)
    {
        [self removeObjectForKey:aKey];
    }
    else
    {
        [self setObject:anObject forKey:aKey];
    }
}

@end

然后像这样整理你的字典:

NSMutableDictionary* values = [NSMutableDictionary dictionary];
[values setObjectOrRemoveIfNil:time_service forKey:@"time_service"];
[values setObjectOrRemoveIfNil:id_service forKey:@"id_service"];
//Keep going with the rest of your values.

最后我们像您一样使用该字典:

 [historialServicios addObject:values];