【问题标题】:Decode JSON in rails simple string raises error在 Rails 简单字符串中解码 JSON 会引发错误
【发布时间】:2011-05-27 17:57:31
【问题描述】:

我正在尝试在 json 中对纯字符串进行往返编码/解码,但出现错误。

在轨道 2.3 中。 w/ ruby​​ 1.8.6,它曾经可以工作。

>> puts ActiveSupport::JSON.decode("abc".to_json)
abc
=> nil

在带有 ruby​​ 1.9.2 的 rails 3.1beta1 中,它会引发错误。

ruby-1.9.2-p180 :001 > puts ActiveSupport::JSON.decode("abc".to_json)
MultiJson::DecodeError: 706: unexpected token at '"abc"'
    from /home/stevenh/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/json/common.rb:147:in `parse'
    from /home/stevenh/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/json/common.rb:147:in `parse'
    from /home/stevenh/.rvm/gems/ruby-1.9.2-p180/gems/multi_json-1.0.1/lib/multi_json/engines/json_gem.rb:13:in `decode'
    [...]

这与nil.to_json cannot be parsed back to nil? 讨论的问题几乎相同

但 nil 过去也可以在 2.3/1.8.7 中工作。

puts ActiveSupport::JSON.decode(nil.to_json)
nil

这是新常态吗?

【问题讨论】:

  • 由于字符串“abc”不是有效的 JSON,因此 DecodeError 似乎适合我。
  • 我必须同意@polarblau,尤其是因为: ruby​​-1.9.2-p180 :012 > ActiveSupport::JSON.decode({:abc => "test"}.to_json) => {"abc"=>"测试"}
  • @polarblau, @Yardboy:我不同意:ActiveSupport::JSON.decode("abc".to_json) 解码 "\"abc\"" 而不是“abc”。问题是解码器不能正确处理简单的字符串。
  • @mosch 也许吧。再深入一点,问题似乎出现在 3.1.0.rc1 中,当时 ActiveSupport JSON 后端被替换为 MultiJson(拉取请求:github.com/rails/rails/pull/289)。我向 multi_json github 项目提交了一个问题,询问这个问题 (github.com/intridea/multi_json/issues/17) - 也许他们会有一些见解。
  • @Yardboy:感谢您的工作。很高兴知道:它不起作用,也不应该;)

标签: ruby-on-rails json


【解决方案1】:

此更改发生在 Rails 3.1.0.rc1 中包含的 switch from ActiveSupport's JSON backend to MultiJson 中。根据MultiJson project team,由于RFC4627 的JSON 语法规范,当前行为是正确的,而之前的实现是错误的:

2.  JSON Grammar

   A JSON text is a sequence of tokens.  The set of tokens includes six
   structural characters, strings, numbers, and three literal names.

   A JSON text is a serialized object or array.

      JSON-text = object / array

由于"abc""/"abc/"" 都不是序列化对象或数组,因此尝试解码它们时出错是合适的。

JSON website 中的图表强化了这一规范。

话虽如此,这似乎意味着 to_json 实现中的一个错误会导致:

ruby-1.9.2-p180 :001 > "abc".to_json
 => "\"abc\""

【讨论】:

    【解决方案2】:

    是的,Rails3 中发生的事情是新常态。您说明的变化似乎反映了一个成熟的框架。

    名为“encode”和“decode”的方法应该完全符合the JSON spec,并且彼此相反。

    另一方面,String#to_json 是一种行为类型的方法,当 Array#to_json 或 Hash#to_json 遇到 String 值时,它可以方便地构建更复杂的 JSON 对象,这些对象可能在内部(在 ActiveSupport 中)使用它们的组成元素之一。

    【讨论】:

      【解决方案3】:

      如果您需要恢复该行为,请关注these steps,即

      # in your Gemfile
      gem 'yajl-ruby'
      
      # in your application.rb
      require 'yajl/json_gem'
      

      在这些步骤之后:

      Loading development environment (Rails 3.2.8)
      [1] pry(main)> puts ActiveSupport::JSON.decode("abc".to_json)
      abc
      => nil
      [2] pry(main)> puts ActiveSupport::JSON.decode(nil.to_json)
      
      => nil
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2017-11-26
        • 2012-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多