Ruby 不使用带引号的键解析JSON

Ruby 不使用带引号的键解析JSON,ruby,json,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/js

我知道在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"}
>> 

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

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

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"}

如果数据的格式非常好,则可以使用简单的正则表达式:

irb(main):009:0> '{name:"hello", age:"23"}'.gsub(/([a-z]+):/, '"\1":')
=> "{\"name\":\"hello\", \"age\":\"23\"}"
(回答我自己的问题)floyd发布的代码片段与我尝试的代码片段类似——它失败了,因为我的一些字符串包含冒号。但我坚持并找到了解决办法:

gsub(/([\{|\,}])\s*([a-zA-Z]+):/, '\1 "\2":')
比以前工作得好

gsub(/([a-z]+):/, '"\1":')

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

我对第三方数据馈送也有同样的问题,但我的数据馈送会返回一个更复杂的类似JSON的响应,而gsub解决方案无法处理。经过一些研究,这些数据提要实际上是JavaScript对象文本,不需要引用键

为了解决这个问题,我添加了execjs gem并安装了node.js(rubyracer gem可能也可以)。完成后,下面返回正确解析的ruby哈希

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

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

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

上述部分假设键仅包含字母;我们的一些包含下划线、空格等。更简单的说法是“任何不是单引号的字符”(在我们的例子中,所有键都用单引号括起来)。

如果不是JSON,就不是JSON。它可能表面上与之相似,但正确的解决方案是修复源代码,这样它实际上会给JSON一个类似于JSON的isntead。不幸的是,我无法控制源代码,它来自第三方。我想你那里有的是YAML,而不是JSON。因此,请使用YAML解析器。例如,他要求什么就需要什么@floyd有下面的解决方案——Ruby的JSON库有非严格模式吗?IIRC,Perl的JSON CPAN模块将对此进行解析,因为它允许Javascript,但不像上面那样允许JSON。谢谢你,尽管我现在使用的是1.8.7,但这不是一个选项。非常干净的解决方案!谢谢更干净的方法是利用谷歌提供的信息,而不是寻找另一块宝石。这可能非常危险。。。(例如,如果您从服务器
{a:1};`rm-rf/`
)获取旧线程,但对@ghayes'而言,问题是:eval([..”).gsub(“`,“”)”)。问题是您的正则表达式还将替换引用值中的“key=”实例,这是您不想要的。
'{name:“hello”,age:“23”}。gsub(/([\w]+):/,““““\1”)
使它更健壮一些!如果值是时间戳,则会失败。例如{name:“Hello”,time:“12:59:59”}
JSON.parse(broken_json_string.gsub(/'([^']+)':/, '"\1":'))