16

私はこの問題に困惑しています。

ActiveSupport::JSONto_jsonさまざまなコア オブジェクトで定義されており、JSON gem も同様です。ただし、実装は同じではありません。ActiveSupport バージョンは引数を取り、JSON gem バージョンは引数を取りません。

JSON gem を必要とする gem をインストールしましたが、アプリが壊れました。問題はto_json、オブジェクトのリストを返すコントローラーで使用していることですが、返される属性を制御したいということです。

システムのどこかでコードを実行するrequire 'json'と、次のエラー メッセージが表示されます。

TypeError: wrong argument type Hash (expected Data)

オンラインで読んだことをいくつか試して修正しましたが、何も機能しませんでした。ActiveSupport::JSON.decode代わりに使用するように宝石を書き直しましたJSON.parse

これは機能しますが、持続可能ではありません... JSON gem を必要とする gem を使用するたびに gem をフォークすることはできません。

更新:この問題の最善の解決策は、Rails 2.3 以降にアップグレードすることです。これにより、この問題は修正されました。

4

6 に答える 6

20

UPDATE : Rails 3.2 でも、同じ問題が未修正のままです。json gem を強制的にロードして上書きする厄介なハックです。

最終的に、ActiveSupportを完全にバイパスするために、次のコードになりましたto_json。に入れると、JSON文字列を生成したり実行したりconfig/initializers/patches.rbできます。何にも衝突しない、保証されています。{}.jsonize[].jsonize

# Undo the effect of 'active_support/core_ext/object/to_json'
require 'json'
[Object, Array, Hash].each do |klass|
  klass.class_eval <<-RUBY, __FILE__, __LINE__
    def jsonize(options = nil)
      ::JSON.generate self, :quirks_mode => true
    end
  RUBY
end

8 行のコードにより、アプリは JSON エンコーディングで50 倍高速になります。おそらくあなたも同じことをしたいでしょう。:)


Rails 2.3.8まで同様の問題がありました。

問題は、それActiveSupport::JSON.backend = 'JSONGem'が中途半端な解決策であり、まだいくつかのエンコーダーを自分で上書きする必要があることです。(警告: MultiJson を使用する Rails 3.x の場合はActiveSupport::JSON.backend = :json_gem、少なくともそれが必要です。

私の場合、JSON gem 1.4.3 の方が、ascii ではなく有効な UTF8 文字を不要な形式でやみくもにエンコードしないという点で優れているため、上書きする必要がありString#to_jsonました。"\uXXXX"シリアライゼーション用) と読みやすい結果 ("日本語"私の目には よりセクシーに見えます"\u65e5\u672c\u8a9e")。

これが私が使ってきたモンキーパッチです - 次のコードを入れてくださいconfig/initializers/patches.rb

module ActiveSupport
  module JSON
    module Encoding
      class << self
        def escape(string)
          ::JSON.generate([string])[1..-2]
        end
      end
    end
  end
end

to_json文字列、配列、ハッシュなど、何にでも自由に使用できます。

于 2010-07-19T22:23:26.313 に答える
4

更新 この修正は、Rails < 2.3 にのみ適用されます。Giles が以下で言及しているように、彼らは 2.3 でこれをほぼ同じ手法を使用して内部的に修正しました。ただし、Rails との互換性に対する json gem の以前の試み( json/add/rails) には注意してください。明示的に要求された場合、すべてが再び完全に破壊されます。

require 'json'ステートメント自体がその例外を発生させるということですか? それとも、電話@something.to_json(:something => value)をかけたときにエラーが発生するということですか?後者は私が期待するものです。JSON gem を必要とする問題がある場合、何が起こっているのかわかりません。

oauth gemでこの問題に遭遇しました。to_json私の場合、oauth gem は実装に依存しないため、真の競合はありません。したがって、問題は、JSON が ActiveSupport 宣言を破壊していることです。ActiveSupport が読み込まれる前に json を要求するだけでこれを解決しました。パッティング

require 'json'

内部でRails::Initializerトリックを行いました(ただし、ブロックの後に配置することはできませんでした)。

これにより、代わりに ActiveSupport がデフォルトの JSON 実装を上書きできます。

のJSON実装に実際に依存するgemを使用しているto_json場合は、小川を上っています。これは間違いなく最悪のメタプログラミングであり、Rails と JSON gem の開発者が競合を解決することをお勧めします。

短期的には、gem の作成者は両方の実装をサポートすることでギャップを埋めることができるかもしれません。これは、宝石がメソッドをどのように使用するかに応じて、多かれ少なかれ実現可能です。最悪のシナリオは、公式のフォーク (すなわちgemgem-rails) です。

于 2009-04-15T19:10:52.553 に答える
3

しばらくこれと戦った後..最も簡単な解決策は次のとおりです。

if defined?(ActiveSupport::JSON)
  [Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
   klass.class_eval do
    def to_json(*args)
      super(args)
    end
    def as_json(*args)
      super(args)
    end
   end
  end
end

activesupportがロードされた後、どこにでも置いてください..

于 2012-09-07T20:16:09.053 に答える
0

2.3で修正されたと確信していますが、その方法を思い出せません。

于 2009-08-04T19:39:37.707 に答える
0

私のユニークなケースではありますが、Rails アプリを (config/environment.rb ロードから) 実際にロードした Ruby (非レール) アプリと、json を参照するいくつかの gem がありました。これは、Rails アプリの environment.rb ファイルを単純に変更することができなかったという事実のために、私に大きな頭痛の種を引き起こしました。恐ろしい TypeError: wrong argument type Hash (expected Data) メッセージを発生させずに json を機能させるために、多くの gem をフォークすることになりました。

上記のコミュニティ wiki の回答とは正反対です... http://blog.swivel.com/code/2009/03/active-support-and-json-gems-dont- 基本的に require 'active_support' BEFORE require 'json'の呼び出しを推奨するplay-nice.html

これが私がそれを機能させる唯一の方法であり、何ヶ月もかけてすべてを試したと信じています.

于 2010-04-03T23:25:32.637 に答える
0

まだ試していませんが、Rails 2.3.3 ではある程度制御できるようです。

ActiveSupport::JSON.backend = 'JSONGem'

ここで見つかりました

于 2010-01-20T09:41:08.250 に答える