我想解码一个带有\u0022
字符的json字符串。
我成功了:
>> ActiveSupport::JSON.decode("{\"json\":{\"difficulty\":1}}")
=> {"json"=>{"difficulty"=>1}}
但失败了:
>> ActiveSupport::JSON.decode("{\"json\":{\"difficulty\":\"test\\u0022test\"}}")
StandardError: Invalid JSON string
from /home/.../.rbenv/versions/1.8.7-p358/lib/ruby/gems/1.8/gems/activesupport-2.3.15/lib/active_support/json/backends/yaml.rb:14:in `decode'
from /home/.../.rbenv/versions/1.8.7-p358/lib/ruby/gems/1.8/gems/activesupport-2.3.15/lib/active_support/json/decoding.rb:14:in `__send__'
from /home/.../.rbenv/versions/1.8.7-p358/lib/ruby/gems/1.8/gems/activesupport-2.3.15/lib/active_support/json/decoding.rb:14:in `decode'
from (irb):11
我希望将\u0022
字符替换为另一个字符,但我不能这样做,因为当应用程序收到请求时,它会在rails的参数解析过程中进行;除非我覆盖了json decode chore方法,我宁愿避免这种方法。
仅供参考:我在Ruby 1.8.7-p358& Rails 2.3.15&我不能改变它。
答案 0 :(得分:0)
我认为这与Syck有关,Syck是(非常)旧版Ruby中使用的旧YAML库。这与YAML有什么关系?在ActiveSupport 2.3.15中,JSON解码使用YAML.load
来解析JSON,因为JSON恰好是YAML的子集。
快速搁置:在ActiveSupport 2.3.18中,ActiveSupport :: JSON :: Backends :: Yaml不再使用YAML后端解码YAML,ActiveSupport::JSON::Backends::Yaml#decode
如下所示:
def decode(json)
raise "The Yaml backend has been deprecated due to security risks, you should set ActiveSupport::JSON.backend = 'OkJson'"
end
使用过时版本的Ruby和Rails会产生非常严重的后果。升级到安全版本仍然支持的版本,否则您会感到抱歉。严重。
无论如何,让我们仔细看看你的数据。我怀疑你知道,UTF-8字符U+0022
is a double-quote。所有的转义让事情变得混乱,所以让我们看看我们实际拥有的字符串:
str = "{\"json\":{\"difficulty\":\"test\\u0022test\"}}"
puts str
# => {"json":{"difficulty":"test\u0022test"}}
FWIW在这里使用Ruby的替代字符串语法更具可读性,例如:
str = %Q[{"json":{"difficulty":"test\\u0022test"}}]
puts str
# => {"json":{"difficulty":"test\u0022test"}}
无论哪种方式,文字\
后跟u0022
。到现在为止还挺好。现在让我们尝试用Syck解析它(我使用的是Ruby 2.2,但在这种情况下并没有什么区别):
require "syck"
str = %Q[{"json":{"difficulty":"test\\u0022test"}}]
Syck.load(str)
# => .../syck.rb:145:in `load': syntax error on line 0, col 38: `# Transforms the subclass name found i}}' (ArgumentError)
我不知道Syck的错误消息为何如此奇怪,但无论如何我们都可以看到Syck试图解析这个JSON。现在让我们用现代的YAML解析器来尝试它:
require "psych"
str = %Q[{"json":{"difficulty":"test\\u0022test"}}]
Psych.load(str)
# => {"json":{"difficulty":"test\u0022test"}}
效果很好!
所以你有几个选择。
您可以升级到仍然维护的Ruby版本,没有安全漏洞,并且有一个没有破坏的YAML解析器。
您可以升级到仍然维护的Rails版本,没有安全漏洞,并且没有使用损坏的YAML解析器来解析JSON。
您可以安装Psych,它可以作为旧版Ruby的宝石。