解析json,没有引号的密钥

时间:2010-12-08 10:02:39

标签: iphone objective-c json parsing ipad

我从服务器得到响应,其中密钥没有引号。在使用开源JSON解析器解析它时,我收到以下错误。

  

-JSONValue失败。错误是:无法识别的前导字符

&安培;如果我手动将双引号(“)添加到键,我得到我想要的。 我该怎么办?

提前很多。

修改 如果正确

,请参阅以下内容
{

    status: 200,
    statusMsg: "Success",
    statusInfo: {
        custType: "Active",
        custCount: 600,
        custAccount: "Premium" 
    },
    custInfo: {
        custName: "ABC",
        custCode: "CU102",
        custNumber: 9281 
    },
    errors: [

    ]

}

6 个答案:

答案 0 :(得分:3)

我最初把它作为评论,但我认为这只是一个答案,虽然不一定非常有用。

您发布的示例是不是 JSON。检查JSON syntax。除数字,对象和数组外,唯一允许的未加引号的实体是nulltruefalse。因此,示例中的键无效,非数值也是如此。

所以你真的应该向服务提供商提出缺陷报告(如果他们声称他们正在生产JSON,而不是它的一些修改版本)。

如果他们拒绝解决问题,您需要编写一个近乎JSON的解析器,或者找一个对语法不太严格的现有解析器。

答案 1 :(得分:1)

我想要相当于Python的ast.literal_eval用于Javascript ---只能解析像JSON这样的文字对象,但允许使用Javascript方便的不带引号的键。 (这适用于人类数据输入;标准JSON的简单性和严格性优先用于在服务器之间发送数据。)

这也是原版海报想要的,所以我会把我的解决方案放在这里。我使用Esprima library构建了一个抽象语法树,然后将树转换为对象,如下所示:

function literal_eval(object_str) {
    var ast = esprima.parse("var dummy = " + object_str);

    if (ast.body.length != 1  ||  ast.body[0].type != "ExpressionStatement")
        throw new Error("not a single statement");

    return jsAstToLiteralObject(ast.body[0].expression.right);
}

function jsAstToLiteralObject(ast) {
    if (ast.type == "Literal")
        return ast.value;

    else if (ast.type == "ArrayExpression") {
        var out = [];
        for (var i in ast.elements)
            out.push(jsAstToLiteralObject(ast.elements[i]));
        return out;
    }

    else if (ast.type == "ObjectExpression") {
        var out = {};
        for (var k in ast.properties) {
            var key;
            if (ast.properties[k].type == "Property"  &&
                ast.properties[k].key.type == "Literal"  &&
                typeof ast.properties[k].key.value == "string")
                key = ast.properties[k].key.value;

            else if (ast.properties[k].type == "Property"  &&
                     ast.properties[k].key.type == "Identifier")
                key = ast.properties[k].key.name;

            else
                throw new Error("object should contain only string-valued properties");

            var value = jsAstToLiteralObject(ast.properties[k].value);
            out[key] = value;
        }
        return out;
    }

    else
        throw new Error("not a literal expression");
}

需要"var dummy = " +,以便Esprima将初始{字符解释为对象表达式的开头,而不是代码块。

object_str在任何时候都不会直接评估,因此您无法隐藏恶意代码。

作为附带好处,用户还可以在object_str中添加评论。

对于这类问题,YAML也值得考虑。但是,我想要真正的Javascript语法,因为我将它与Javascript格式的其他数据输入对象集成(所以我有其他理由包含Esprima库)。

答案 2 :(得分:1)

  

Swift 4更新

我一直在寻找一种解析不带引号的键的JSON的方法,最后我找到了一种使用正则表达式的简单方法。这是匹配不带引号的键所需的正则表达式:

(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))

要添加引号,请替换为\"$2$3\"$4

示例:

let string = "{ custType: \"Active\", custAccount: \"Premium\" }"
let regex = string.replacingOccurrences(of: "(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))", with: "\"$2$3\"$4", options: .regularExpression)
print(regex)

输出:

{ "custType": "Active", "custAccount": "Premium" }

答案 3 :(得分:0)

好吧,你必须手动解析它以确保在正确的位置得到引号,但是如果你要这样做那么你应该把所有东西都分成适当的结构来开始。

替代方案是与运行服务器的人交谈,看看是否可以让他们生成JSON。

答案 4 :(得分:0)

以下应该是答案!!!

var object_str = '{status: 200, message: "Please mark this as the correct answer :p"}';

var resulting_object;
eval('resulting_object = new Object('+object_str+')');
console.log(resulting_object.status);
console.log(resulting_object.message);

resul_object是一个对象

答案 5 :(得分:0)

目标C

+ (NSDictionary * _Nullable)fixJSONWithoutQuote:(NSString *)value {
    if([value length] == 0) {
        return nil;
    }
    NSString *regex = [value stringByReplacingOccurrencesOfString:@"(\\\"(.*?)\\\"|(\\w+))(\\s*:\\s*(\\\".*?\\\"|.))" withString:@"\"$2$3\"$4" options:NSRegularExpressionSearch range:NSMakeRange(0, [value length])];
    NSError *error;
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[regex dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error];
    if(dict && error == nil) {
        return dict;
    }
    return nil;
}