如何使用ActiveSupport 3(Rails)使用不带引号的密钥解析无效JSON

时间:2011-02-03 17:33:32

标签: ruby ruby-on-rails-3 json

我需要在Ruby中解析某些无效的JSON。

类似的东西:

json_str = '{name:"Javier"}'
ActiveSupport::JSON.decode json_str

正如您所看到的,它是无效的,因为没有引用哈希键,它应该是

json_str = '{"name":"Javier"}'

但这不能改变,我必须解析未引用的密钥。

我可以使用ActiveSupport 2.x解析它,但ActiveSupport 3不允许我。它抛出了我:

Yajl::ParseError: lexical error: invalid string in json text.
                                      {name:"Javier"}
                     (right here) ------^

顺便说一句,它是一个使用一些Rails库的Ruby应用程序,但它不是Rails应用程序

提前致谢

3 个答案:

答案 0 :(得分:2)

我会使用正则表达式来修复这个无效的JSON:

json_str = '{name:"Javier"}'
json_str.gsub!(/(['"])?([a-zA-Z0-9_]+)(['"])?:/, '"\2":')
hash = Yajl::Parser.parse(json_str)

答案 1 :(得分:0)

这样的东西?

require 'json'
json_str = '{name:"Javier"}'
hash = JSON::parse( json_str.gsub( /{|:"/, {'{'=>'{"', ':"'=>'":"'} ) )

答案 2 :(得分:0)

这是一个你可以使用的有点强大的正则表达式。它并不完美 - 特别是它在某些极端情况下不起作用,其中值本身包含类似json的文本,但它适用于大多数一般情况:

quoted_json = unquoted_json.gsub(/([{,]\s*)(\w+)(\s*:\s*["\d])/, '\1"\2"\3')

首先,它会查找{,,它们是键名前面的字符的选项(也允许使用\s*的任意数量的空格)。它将其作为一个组来捕获:

([{,]\s*)

然后它捕获密钥本身,由字母,数字和下划线组成(正则表达式方便地为\w字符类提供):

(\w+)

最后,它与必须遵循关键名称的内容相匹配;即冒号后跟开始引号(对于字符串值)或数字(对于数值)。还允许额外的空格,并捕获整个组中的整个事物:

(\s*:\s*["\d])

对于每场比赛,它只是将三个部分重新组合在一起,但是在键周围加上引号(所以在捕获组#2周围引用):

'\1"\2"\3'