如何区分布尔和&反序列化JSON后的整数?

时间:2014-03-17 07:03:16

标签: objective-c json nsnumber

所以,这就是问题所在:

  1. __ NSCFBoolean& __NSCFNumber是私有的
  2. - [NSNumber boolValue]会将0/1转换为NO / YES
  3. 现在不是问题,在JSON中将false / true / 0/1作为可能的值是一个坏主意
  4. 那么如何才能正确区分反序列化的布尔值&整数值?

4 个答案:

答案 0 :(得分:2)

tldr:使用kCFBooleanFalse& kCFBooleanTrue正确检测布尔值!

持有布尔值的NSNumber是__NSCFBoolean私有类的实例,它是一个特殊的野兽 - 指向该类的任何实例的指针将是kCFBooleanFalse或kCFBooleanTrue,这使我们能够使用此代码(ARC):

if ([value isKindOfClass::[NSNumber class]]) 
{
    if ((__bridge CFBooleanRef)value == kCFBooleanTrue) 
    {
        // value == @YES
    } 
    else if ((__bridge CFBooleanRef)value == kCFBooleanFalse) 
    {
        // value == @NO
    }
    else
    {
       // value is other type of number (int, float, etc...)
    }
}

答案 1 :(得分:1)

答案很简单 - 不要。

您的数据解析器应该知道每个地方的期望值。只是不要混合数字和布尔值。

答案 2 :(得分:1)

不幸的是,无法保证您可以确定用于创建NSNumber的源类型。 NSNumber文档声明它与CFNumber无桥接,换句话说,一个实例可以被视为另一个实例(在ARC的情况下具有适当的桥接转换)。这两种类型的文档都明确指出,虽然可以通过CFNumberGetType()objCType确定存储在任一实例中的值的类型,但这可能相同用实例构造的类型。这来自CFNumber文档:

  

在创建新的CFNumber对象时,不一定会保留对CFNumberCreate的调用中指定的类型 - 它使用创建函数认为合适的任何内部存储类型。

如果您检查CFNumberTypeenum代表CFNumber中的值类型,则BOOL没有值。

此外,还有CFBoolean类型用于存储已包含的布尔值,它未定义为CFNumber的子类型,或者在其文档中提及或NSNumber

如果您创建NSNumber且值为BOOL,则发现当前,但结果已被视为{{1}定义的常量值之一没有文档说明这是定义的行为。

因此,为了好奇,您可以尝试解决这个问题,不要依赖于生产代码中的任何特定行为。

注意: CFBoolean被定义为Core Foundation属性列表类型之一。可以通过使用各种免费桥接关系等证明CFBoolean必须免费桥接到CFBoolean。但是我不认为保证来自JSON的布尔必须是NSNumber实例,尽管可能是 ...

答案 3 :(得分:0)

我提出了另一个解决方案:

id value_from_json = json[key];
if([value_from_json isKindOfClass[NSNumber class]]) {
    NSNumber *number_value = (NSNumber *)value_from_json;
    // Observe that the check is "isEqualToValue", not "isEqualToNumber"
    if([number_value isEqualToValue:@YES] || [number_value isEqualToValue:@NO]) {
        // It's a boolean
    } else {
        // It's not a boolean
    }
}

我测试了它,它可以在“true”,true和1之间进行distingush(和“false”,false和0)