美文网首页
异常JSON格式化,取巧方式

异常JSON格式化,取巧方式

作者: yellowzhou | 来源:发表于2018-11-09 14:49 被阅读0次

    在开发中,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

    相关文章

      网友评论

          本文标题:异常JSON格式化,取巧方式

          本文链接:https://www.haomeiwen.com/subject/nxcoxqtx.html