异常JSON格式化,取巧方式

2018-11-09  本文已影响0人  yellowzhou

在开发中,JSON 数据交互非常平凡,行业的标准处理xml就是JSON,但是如果客户使用非标准化的JSON就会出现无法直接从JSON字符转换成JSON对象

标准 JSON

{
    "message": {
        "list": [
            "张三",
            "李四'小李'"
        ],
        "info": {
            "city": "广州市"
        }
    },
    "other": {
        "type": 1,
        "var": {}
    }
}

当在JSON中key:value 采用 单引号或者没有加引号,在转换对象时会失败。
那么如何避免这个问题呢?
之前在网络上查到很多方法,采用正则表达的方式,先进行JSON字符的格式化,但是始终做不到匹配各种情况下的JSON数据

- (NSString *)changeJsonStringToTrueJsonString:(NSString *)json{
    // 将没有双引号的替换成有双引号的
    NSString *validString = [json stringByReplacingOccurrencesOfString:@"(\\w+)\\s*:([^A-Za-z0-9_])"
                                                            withString:@"\"$1\":$2"
                                                               options:NSRegularExpressionSearch
                                                                 range:NSMakeRange(0, [json length])];
    //把'单引号改为双引号"
    validString = [validString stringByReplacingOccurrencesOfString:@"([:\\[,\\{])'"
                                                         withString:@"$1\""
                                                            options:NSRegularExpressionSearch
                                                              range:NSMakeRange(0, [validString length])];
    validString = [validString stringByReplacingOccurrencesOfString:@"'([:\\],\\}])"
                                                         withString:@"\"$1"
                                                            options:NSRegularExpressionSearch
                                                              range:NSMakeRange(0, [validString length])];
    
    //再重复一次 将没有双引号的替换成有双引号的
    validString = [validString stringByReplacingOccurrencesOfString:@"([:\\[,\\{])(\\w+)\\s*:"
                                                         withString:@"$1\"$2\":"
                                                            options:NSRegularExpressionSearch
                                                              range:NSMakeRange(0, [validString length])];
    return validString;
}
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
        responseStr = [responseStr stringByReplacingOccurrencesOfString:@"'" withString:@"\""];
        NSDictionary* dic =[responseStr objectFromJSONString];
        if (!dic) { // it's => it"s => it's
            responseStr = [responseStr stringByReplacingOccurrencesOfString:@"([A-Za-z0-9_])\"([A-Za-z0-9_])"
                                                                 withString:@"$1\'$2"
                                                                    options:NSRegularExpressionSearch
                                                                      range:NSMakeRange(0, [responseStr length])];
            dic =[responseStr objectFromJSONString];
        }

异常数据

"{\"message\": {\"list\": [\"张三\",\"李四'小李'\"],\"info\": {\"city\": \"广州市\"}},\"other\": {'type': 1,'var': {}}}"
"{message: {\"list\": [\"张三\",\"李四'小李'\",\"i'am iOS\"],\"info\": {\"city\": \"广州市\"}},\"other\": {type: 1,'var': {}}}"

解决方案

为适配以上情况,可以巧妙的使用JS中JSON对象进行解析,这样可以避免正则表达晦涩难懂,并且不易维护等问题,在 NSJSONSerialization 创建category,每一次json对象化时自动解析,该方案还可以避免使用AFNetworking因为response中JSON对象化不了,直接返回nil

#import "NSJSONSerialization+Extension.h"
#import <objc/runtime.h>
#import <JavaScriptCore/JavaScriptCore.h>

@implementation NSJSONSerialization (Extension)

+(void)load {
    method_exchangeImplementations(class_getClassMethod([self class], @selector(JSONObjectWithData:options:error:)),class_getClassMethod([self class], @selector(myJSONObjectWithData:options:error:)));
}

+ (nullable id)myJSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error
{
    if (!data) {
        return nil;
    }
    id object = [self myJSONObjectWithData:data options:opt error:error];
    if (object) {  
        return object;
    }
    
    NSString *text = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
    if (!data || text.length == 0) {
        return nil;
    }
    JSValue *value = [[[JSContext alloc]init] evaluateScript:[NSString stringWithFormat:@"JSON.stringify(%@)",text]];
    NSData *jsonData = [[value toString] dataUsingEncoding:NSUTF8StringEncoding];
    object = [self myJSONObjectWithData:jsonData options:opt error:error];
    if (object) {
        return object;
    }
    return text;
}
- (void)test {
    NSString *json = @"{message: {\"list\": [\"张三\",\"李四'小李'\",\"i'am iOS\"],\"info\": {\"city\": \"广州市\"}},\"other\": {type: 1,'var': {}}}";
    NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
    id object = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    NSLog(@"object: %@",object);
}
{
    message =     {
        info =         {
            city = "\U5e7f\U5dde\U5e02";
        };
        list =         (
            "\U5f20\U4e09",
            "\U674e\U56db'\U5c0f\U674e'",
            "i'am iOS"
        );
    };
    other =     {
        type = 1;
        var =         {
        };
    };
}
result.png
上一篇下一篇

猜你喜欢

热点阅读