0

对于在 Rails 项目之外依赖 Ruby 的 JSON 序列化的许多人来说,这个问题将会浮出水面。当他们尝试在 Rails 项目中使用他们的代码时,它不会按预期工作。

以下代码从 Ruby(无 Rails)运行,打印 A。从 rails 控制台运行时,它打印 Hash。

这意味着我的 json 序列化在我的命令行 lib/app 中有效,但在导入 Rails 项目时无效。

这是什么原因/解决方法?

require 'json'

class A
  def to_json(*a)
    {:json_class => self.class.name}.to_json(*a)
  end
  def self.json_create(o)
    A.new
  end
end

class B
  attr_accessor :value
  def initialize(value)
    @value = value
  end

  def to_json(*a)
    {:json_class => self.class.name, :value => value}.to_json(*a)
  end
  def self.json_create(o)
    B.new(o['value'])
  end
end
b = JSON.parse(B.new(A.new).to_json)
puts b.value.class

Ruby 是 1.9.3,Rails 是 3.2.10

4

3 回答 3

2

问题是 Rails 使用ActiveSupport::JSON。

对于序列化,它使用 as_json,而不是 to_json。所以这条线

 {:json_class => self.class.name, :value => value}.to_json(*a)

在散列中不包含 JSON 版本的值,因为 A 类没有 as_json 方法。为了让你的代码在 Ruby 和 Rails 中都能正常工作,你需要显式调用 A::to_json 和 A::json_create 方法,如下所示:

  def to_json(*a)
    {:json_class => self.class.name, :value => JSON.dump(value)}.to_json(*a)
  end
  def self.json_create(o)
    B.new(A.json_create(o['value']))
  end

然后打电话,b = JSON.parse(JSON.dump(B.new(A.new)))

这将修复示例,但我认为您可能想阅读to_json vs as_json 的解释并适当地修改您的代码。

于 2013-01-13T08:22:45.707 回答
1

根据其他人的说法,答案是肯定的。 http://www.rubyhood.com/2011/06/rails-spoiled-standard-json-library.html

简而言之,让 as_json 做 to_json 所做的事情。这让我得到了我想要/期望的东西(以及我从纯 Ruby - Rails 中得到的东西)。

于 2013-01-14T23:30:40.113 回答
0

对于那些仍在徘徊为什么在 Rails 中发生奇怪行为的人,可以在以下位置找到解释: https ://github.com/flori/json/compare/v1.6.7...v1.6.8 和 https://github.com /intridea/multi_json/compare/v1.5.0...v1.5.1

由于在这些版本升级中 JSON.parse 的工作方式不同。JSON.load 可能仍然有用。最快的解决方法是:

gem 'json', '1.6.7'
gem 'multi_json', '1.5.0'

但留下一些安全问题。建议在需要时显式提供create_additions: trueJSON 解析。

于 2013-02-16T09:17:10.930 回答