Does NSJSONSerialization deserialize numbers as NSDecimalNumber?

后端 未结 4 2084
甜味超标
甜味超标 2021-02-08 03:37

Take the following piece of code:

NSError *error;
NSString *myJSONString = @\"{ \\\"foo\\\" : 0.1}\";
NSData *jsonData = [myJSONString dataUsingEncoding:NSUTF8St         


        
4条回答
  •  花落未央
    2021-02-08 04:10

    The short answer is that you should not serialize to JSON if you require NSDecimalNumber levels of precision. JSON has only one number format: double, which has inferior precision to NSDecimalNumber.

    The long answer, which is of academic interest only, because the short answer is also the right answer, is "Not necessarily." NSJSONSerialization does sometimes deserialize as NSDecimalNumber, but it is undocumented, and I have not determined, what the set of circumstances under which it does is. For instance:

        BOOL boolYes = YES;
        int16_t int16 = 12345;
        int32_t int32 = 2134567890;
        uint32_t uint32 = 3124141341;
        unsigned long long ull = 312414134131241413ull;
        double dlrep = 1.5;
        double dlmayrep = 1.1234567891011127;
        float fl = 3124134134678.13;
        double dl = 13421331.72348729 * 1000000000000000000000000000000000000000000000000000.0;
        long long negLong = -632414314135135234;
        unsigned long long unrepresentable = 10765432100123456789ull;
    
        dict[@"bool"] = @(boolYes);
        dict[@"int16"] = @(int16);
        dict[@"int32"] = @(int32);
        dict[@"dlrep"] = @(dlrep);
        dict[@"dlmayrep"] = @(dlmayrep);
        dict[@"fl"] = @(fl);
        dict[@"dl"] = @(dl);
        dict[@"uint32"] = @(uint32);
        dict[@"ull"] = @(ull);
        dict[@"negLong"] = @(negLong);
        dict[@"unrepresentable"] = @(unrepresentable);
    
        NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    
        NSDictionary *dict_back = (NSDictionary *)[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    

    and in the debugger:

    (lldb) po [dict_back[@"bool"] class]
    __NSCFBoolean
    (lldb) po [dict_back[@"int16"] class]
    __NSCFNumber
    (lldb) po [dict_back[@"int32"] class]
    __NSCFNumber
    (lldb) po [dict_back[@"ull"] class]
    __NSCFNumber
    (lldb) po [dict_back[@"fl"] class]
    NSDecimalNumber
    (lldb) po [dict_back[@"dl"] class]
    NSDecimalNumber
    (lldb) po [dict_back[@"dlrep"] class]
    __NSCFNumber
    (lldb) po [dict_back[@"dlmayrep"] class]
    __NSCFNumber
    (lldb) po [dict_back[@"negLong"] class]
    __NSCFNumber
    (lldb) po [dict_back[@"unrepresentable"] class]
    NSDecimalNumber
    

    So make of that what you will. You should definitely not assume that if you serialize an NSDecimalNumber to JSON that you will get an NSDecimalNumber back out.

    But, again, you should not store NSDecimalNumbers in JSON.

提交回复
热议问题