在没有引用键的情况下解析JSON

时间:2010-01-13 21:19:09

标签: ruby json

据我所知,在JSON中,键应该用双引号括起来。但是,我正在使用一个不引用它们的数据源,这导致Ruby JSON解析器引发错误。有没有办法执行'非严格'解析?

示例:

>> JSON.parse('{name:"hello", age:"23"}')
JSON::ParserError: 618: unexpected token at '{name:"hello", age:"23"}'
    from /Library/Ruby/Gems/1.8/gems/json-1.1.7/lib/json/common.rb:122:in `parse' 
    from /Library/Ruby/Gems/1.8/gems/json-1.1.7/lib/json/common.rb:122:in `parse'
    from (irb):5
>> JSON.parse('{"name":"hello", "age":"23"}')
=> {"name"=>"hello", "age"=>"23"}
>> 

(我尝试使用正则表达式在解析之前添加引号,但无法使其完全正常工作)。

6 个答案:

答案 0 :(得分:16)

如果数据形成得非常好,那么一个简单的正则表达式可能会这样做:

irb(main):009:0> '{name:"hello", age:"23"}'.gsub(/([a-z]+):/, '"\1":')
=> "{\"name\":\"hello\", \"age\":\"23\"}"

答案 1 :(得分:9)

我在第三方数据Feed中遇到了同样的问题,但我的返回更复杂的类似JSON的响应,gsub解决方案无法处理。经过一些研究后,看来这些数据源实际上是JavaScript对象文字,不需要引用键。

为了解决这个问题,我添加了execjs gem并安装了node.js(therubyracer gem也可能会起作用)。完成后,以下内容返回正确解析的ruby散列。

ExecJS.eval('{name:"hello", age:"23"}')
 => {"name"=>"hello", "age"=>"23"}

答案 2 :(得分:7)

有趣的是,您的示例是有效的ruby 1.9 Hash语法。如果您的数据真的如此简单(键名中没有空格或其他特殊字符),并且您可以在安全的上下文中处理它,那么您可以eval它。

irb(main):001:0> eval '{name:"hello", age:"23"}'
=> {:name=>"hello", :age=>"23"}

这会将符号作为键,因此如果需要将它们转换为字符串,则需要进行后处理:

irb(main):002:0> eval('{name:"hello", age:"23"}').reduce({}) {|h,(k,v)| h[k.to_s] = v; h}
=> {"name"=>"hello", "age"=>"23"}

答案 3 :(得分:2)

gsub(/(\w+)\s*:/, '"\1":')

工作得更好
gsub(/([a-z]+):/, '"\1":')

如果它有空格或大写字母,则失败。

答案 4 :(得分:1)

(回答我自己的问题)floyd发布的片段与我尝试的类似 - 它失败了,因为我的一些字符串包含冒号。但我坚持并找到了解决方案:

gsub(/([\{|\,}])\s*([a-zA-Z]+):/, '\1 "\2":')

答案 5 :(得分:0)

这就是我必须解决的问题:

JSON.parse(broken_json_string.gsub(/'([^']+)':/, '"\1":'))

上面的一些假设键只包含字母;我们中的一些包含下划线,空格等。更容易说“任何不是单引号的字符”(在我们的例子中,所有键都包含在单引号中)。