如何检测字典是空还是空

时间:2015-03-18 16:28:06

标签: ios objective-c nsdictionary

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

-meta
-objects
   |_cabdriver
              |_employee
   |client

对象树下有对象,还有子节点,如cabdriver和client。子节点cabdriver还有另一个名为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
}

如果对象具有所有节点但是有时候节点cabdriver为空并且没有雇员子节点,则一切正常。如果是这种情况,我会抛出异常并且应用程序崩溃。

我如何确定节点员工是否不存在并避免获得例外?

谢谢。

7 个答案:

答案 0 :(得分:2)

您可以声明一个类别来处理注入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]];

答案 1 :(得分:1)

在此尝试:

if( cabdriverLevelDict.allkeys.count ){
    // Do something with the dict
} else {
    // dict is empty
}

答案 2 :(得分:1)

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

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

在Objective-C中,nil对象非常安全。例如,你可以使用objectForKey [@“employee”],所有会发生的结果是你得到nil。你无论如何都可以收到零。

没有必要检查[NSNull null],因为服务器给你的任何其他结果都会使你的app崩溃。只需检查一下你的期望。抛弃不正确的数据很好,如果只有一个字节的数据错误,所有JSON反序列化器都会抛弃所有内容。

有时候你需要多做一些照顾,因为服务器行为不端,你必须应对它。例如,一个服务器应该返回一个字典数组,如果只有一个字典,可能只给你一个字典,所以你要检查例如

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

答案 3 :(得分:1)

正如其他人所指出的,如果传入字典的任何对象都是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等)不是nil。正如您所指出的,它们可能是零,因此您需要有一种方法来检查您所做的每个对象。我建议使用一个NSMutableDictionary,使一个类别方法只添加键/值对,如果它们都不是nil:

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

答案 4 :(得分:0)

检查词典的计数

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

答案 5 :(得分:0)

if (![cabdriverLevelDict isKindOfClass:[NSNull class]] ){
    //do something
}

试试这个

答案 6 :(得分:-2)

你可以尝试

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


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

}];