【问题标题】:Parsing json, key without quotes解析json,key不带引号
【发布时间】:2010-12-08 10:02:39
【问题描述】:

我收到来自服务器的响应,其中密钥不带引号。在使用开源 JSON 解析器解析它时,我收到以下错误。

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

& 如果我手动将双引号 (") 添加到键中,我会得到我想要的。 我该怎么办?

非常感谢。

编辑: 如果正确,请参阅以下内容

{

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

    ]

}

【问题讨论】:

  • 您控制服务吗?如果键不在双引号中,则它不是有效的 JSON。也许您应该通知服务所有者...
  • 菲利克斯·克林+1。无效的 JSON,无效的 NSDictionary 键/值对。服务器应该是固定的。
  • 我已经发布了回复。请看看它是否正确。此外,双引号中的键也一样

标签: iphone objective-c json parsing ipad


【解决方案1】:

我最初将其作为评论放入,但我认为它算是一个答案,尽管不一定很有帮助。

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

因此,您确实应该向服务提供商提出缺陷报告(如果他们声称他们正在生成 JSON,而不是它的某些修改版本)。

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

【讨论】:

  • 这不完全是服务器响应,它只是格式。另外,我错误地从值中删除了双引号。那么它会做出正确的格式,因为我得到了同样的错误。
  • @sole007:密钥仍然无效。 JSON 中的键也必须是字符串。
  • 你的意思是用双引号吗?
  • @sole007:是的。看看我提供的链接。语法很容易理解。
【解决方案2】:

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】:

    我想要相当于 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 中包含 cmets。

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

    【讨论】:

      【解决方案4】:

      好吧,您必须手动解析它以确保将引号放在正确的位置,但如果您要这样做,那么您应该首先将所有内容排序到正确的结构中。

      另一种方法是与运行服务器的人交谈,看看是否可以让他们生成 JSON。

      【讨论】:

        【解决方案5】:

        以下应该是答案!!!

        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);
        

        resulting_object 是一个对象

        【讨论】:

        • 这和eval(object_str)没有什么不同,它具有eval的所有优点和缺点。例如,有人可以在对象中包含非文字代码,例如"{one: 1, two: 2, three: function () { do_something_dangerous(); return 3; }()}"。你会得到一个 {one: 1, two: 2, three: 3} 的对象,但无论是谁给你发送了那个字符串,你只是让你为他们运行一些代码。
        【解决方案6】:

        目标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;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-10-11
          • 1970-01-01
          • 2018-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多