0

この問題は、Railsプロジェクトの外部でRubyのJSONシリアル化に依存している多くの人に表面化するでしょう。Railsプロジェクトでコードを使おうとすると、期待どおりに機能しません。

次のコードはRuby(Railsなし)から実行され、Aを出力します。Railsコンソールから実行されると、ハッシュを出力します。

つまり、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を使用していることです。

シリアル化には、to_jsonではなくas_jsonを使用します。だからライン

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

クラスAにはas_jsonメソッドがないため、ハッシュに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)))

このwlllは例を修正しますが、to_jsonと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

レールで奇妙な動作が発生している理由をまださまよっている人のために、説明は 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: true必要に応じてJSON解析に明示的に提供することをお勧めします。

于 2013-02-16T09:17:10.930 に答える