首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有一种方法来规范来自NSJSONSerialization的json数据?

是否有一种方法来规范来自NSJSONSerialization的json数据?
EN

Stack Overflow用户
提问于 2014-10-24 21:23:50
回答 2查看 741关注 0票数 0

自XCode 6.1以来,iPhone 5S、iPhone 6和iPhone 6+模拟器(全部64位)与32位模拟器(例如iPhone 5模拟器)从以下系统方法返回数据的方式不同(键排序不同)。

代码语言:javascript
复制
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;

密钥排序的这种差异给我带来了一个问题,因为我们计算了该JSON数据的SHA1 (转换为NSString*),并将其用于验证测试。由于顺序更改,SHA1更改,验证失败。

获得SHA1的简化示例代码(非ARC)如下:

代码语言:javascript
复制
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dict
                                                   options:0
                                                     error:&error];
NSString * json = [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] autorelease];

NSString * sha1 = [MyUtils computeSHA1:json];

+(NSString*) computeSHA1:(NSString*)input
{
    const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
    NSData     *data = [NSData dataWithBytes:cstr length:input.length];
    NSNumber* dataLen = [NSNumber numberWithUnsignedInteger:data.length];

    uint8_t    digest[CC_SHA1_DIGEST_LENGTH];

    CC_SHA1(data.bytes, dataLen.unsignedIntValue, digest);

    NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];

    for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02x", digest[i]];

    return output;
}

显然,这种键排序差异不会发生在实际设备上(以前的行为被保留下来)。

我也尝试使用NSJSONWritingPrettyPrinted选项,但是JSON排序在模拟器之间仍然不一致。

因此,问题是:是否有人对如何规范此类JSON数据提出建议,以避免密钥排序更改?或者,是否有任何方法可以获得以前的(32位模拟器)行为?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-27 15:49:34

下面的代码(非ARC)帮助我更好地规范JSON输出。代码假设下面的类方法都在一个名为MyUtils的类中。

只需将要序列化为“规范化JSON”的NSDictionary传递给canonicalJSONRepresentationWithDictionary:

然后返回的NSString*包含序列化的JSON,该JSON以非人类可读的格式按顺序/字母顺序排列键。

代码语言:javascript
复制
+(NSString *) canonicalJSONRepresentationWithDictionary:(NSDictionary *)dict
{
    NSMutableString* json = [NSMutableString string];
    [json appendString:@"{"];

    NSArray* keys = [[dict allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString* a, NSString* b) {
        return [a compare:b];
    }];

    for (int i = 0; i < keys.count; i++) {
        NSString* key = keys[i];
        [json appendFormat:@"\"%@\":", key];

        if ([dict[key] isKindOfClass:[NSString class]]) {
            [json appendFormat:@"\"%@\"", [MyUtils canonicalJSONRepresentationWithString:dict[key]]];
        } else if ([dict[key] isKindOfClass:[NSDictionary class]]) {
            [json appendString:[MyUtils canonicalJSONRepresentationWithDictionary:dict[key]]];
        } else if ([dict[key] isKindOfClass:[NSArray class]]) {
            [json appendString:[MyUtils canonicalJSONRepresentationWithArray:dict[key]]];
        } else {
            return nil;
        }

        if (i < keys.count - 1) {
            [json appendString:@","];
        }
    }

    [json appendString:@"}"];
    return json;
}

+(NSString *) canonicalJSONRepresentationWithArray:(NSArray *) array
{
    NSMutableString* json = [NSMutableString string];
    [json appendString:@"["];

    for (int i = 0; i < array.count; i++) {
        if ([array[i] isKindOfClass:[NSString class]]) {
            [json appendFormat:@"\"%@\"", [MyUtils canonicalJSONRepresentationWithString:array[i]]];
        } else if ([array[i] isKindOfClass:[NSDictionary class]]) {
            [json appendString:[MyUtils canonicalJSONRepresentationWithDictionary:array[i]]];
        } else if ([array[i] isKindOfClass:[NSArray class]]) {
            [json appendString:[MyUtils canonicalJSONRepresentationWithArray:array[i]]];
        } else {
            return nil;
        }

        if (i < array.count - 1) {
            [json appendString:@","];
        }
    }

    [json appendString:@"]"];
    return json;
}

+(NSString *) canonicalJSONRepresentationWithString:(NSString *) string;
{
    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:string, @"a", nil];

    NSError  * error;
    NSData   * jsonData = nil;
    NSString * json     = nil;

    jsonData = [NSJSONSerialization dataWithJSONObject:dict
                                               options:0
                                                 error:&error];

    if (!jsonData) {
        NSLog(@"Got an error serializing json: %@", error);
        return nil;
    } else {
        json = [[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] autorelease];
    }

    NSRange colonQuote = [json rangeOfString:@":\""];
    NSRange lastQuote = [json rangeOfString:@"\"" options:NSBackwardsSearch];
    NSRange range = NSMakeRange(colonQuote.location + 2, lastQuote.location - colonQuote.location - 2);

    NSString* rc = [json substringWithRange:range];

    return rc;
}
票数 -2
EN

Stack Overflow用户

发布于 2014-10-24 21:33:43

字典中的键排序不能得到保证。如果需要对它们进行排序,请将它们放入数组中并对它们进行排序。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26556507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档