2009-03-25 5 views
12

私はこの問題で困惑しています。ActiveSupport :: JSONとJSON gemの間の競合をどのように扱いますか?

ActiveSupport::JSONは、さまざまなコアオブジェクト上にto_jsonと定義しています.JSON宝石も同様です。しかし、実装は同じではありません。ActiveSupportのバージョンには引数があり、JSONの宝石のバージョンには反映されません。

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

どこにでも私のシステムのコードがrequire 'json'私は、このエラーメッセージを取得ん:

TypeError: wrong argument type Hash (expected Data)

を私はそれを修正するためにオンラインで読む物事のカップルを試してみましたが、何も働きました。私はの代わりにActiveSupport::JSON.decodeを使うように宝石を書き直した。

これは機能しますが持続可能ではありません...私はJSONの宝石を必要とする宝石を使用するたびに宝石を捨てることはできません。

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

+1

がなぜこの質問は、「コミュニティのwiki」としてマークされていますか? –

+0

私は、私はそれを試して、それが何を参照してくださいと思ったのか分かりません。 –

+0

私はあなたの痛みを感じました、私はこの混乱がいつかソートされることを願っています – MatthewFord

答えて

2

更新この修正はRails <にのみ適用されます。以下にGilesが述べるように、彼らは内部で2.3と同じ手法を使ってこれを修正しました。しかし、jsonの宝石の以前のRails互換性への試みは注意してください。json/add/rails)、、明示的に必要な場合は、すべてをもう一度やり直すでしょう。

require 'json'ステートメント自体がその例外を呼び起こすのですか?または、@something.to_json(:something => value)に電話するとエラーが表示されますか?後者は、JSONの宝石が必要な問題がある場合、何が起こっているのか分かりません。

oauth gemでこの問題が発生しました。私の場合、oauthの宝石はto_jsonの実装に依存していないので、真の競合はありません。したがって、問題は、JSONがActiveSupport宣言を壊滅させていることです。 ActiveSupportがロードされる前に単にjsonを要求するだけで解決しました。 (ブロックはしませんでした後にそれを入れても)Rails::Initializer内部

require 'json' 

はトリックをした置きます。

これにより、ActiveSupportはデフォルトのJSON実装を奪うことができます。

実際にJSONの実装に依存する宝石をto_jsonに使用している場合、あなたはクリークを上っています。これは間違いなくメタプログラミングの中で最悪ですが、RailsとJSON gemの開発者が競合を解決することを推奨しますが、どちらか一方が下位互換性を失わなければならないので苦しいでしょう。

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

+0

ええ、私はそれが私に多くの痛みを引き起こすto_jsonのRailsバージョンを吹き飛ばす 'json'を必要とするものを使用するとき。 ご意見ありがとうございます。 require 'json/add/rails'を使用することで提案されているオプションが不運になりましたか?私はそれを働かせることはできません。 –

+0

は最初に呼び出すときにのみ必要なので、Railsのバージョンがロードされる前に呼び出すと、プラグインが必要なときに何もしません。実際にこれを確認して、Rails :: Initializerブロックに入れておきます。いい考えはないと思いますが、それは必要ではないと思います。 – gtd

0

私はかなり彼らが2.3でこれを修正したと確信していますが、私はどのように覚えていません。

+0

ええ、私は彼らがto_jsonを直接呼び出すことを取り除いたと思います。代わりにas_jsonを定義するか、JSON.generateまたはActiveSupport :: JSON.encodeを直接呼び出します。そして、新しいJSONバックエンドのものでは、ActiveSupport :: JSON.encodeがあなたの好みのライブラリを使用すると思います。 –

0

私はそれを試していましたが、それはRailsの2.3.3はあなたにいくつかのコントロールを与えるようになっています。私は

ActiveSupport::JSON.backend = 'JSONGem' 

Found here

+0

ええ、Rails 2.3以降でこの問題が修正されています。 –

0

をユニークなケースはいえ、私は非(ルビーを持っていましたrails)アプリケーションと、実際にRailsアプリケーション(config/environment.rbのロード)とjsonを参照しているいくつかの宝石をロードしています。これは、私がRailsアプリケーションのenvironment.rbファイルを単に変更できないという事実のため、大きな頭痛を引き起こしました。 私は恐ろしいTypeError:間違った引数型ハッシュ(予期されたデータ)メッセージを生成せずにjsonを動作させるためにいくつかの宝石を作り出しました。

私は基本的に は「JSON」

を必要とする前に は「active_support」 を必要と呼び出す提唱上記コミュニティのwikiの答えとまったく反対で、この解決策、といくつかの運... http://blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.html を持っていました

これは私がそれを働かせる唯一の方法であり、私は何ヶ月もかけてすべてを試みたと信じています。

18

UPDATE:Rails 3.2の場合でも、同じ問題が修正されません。 jsonの宝石を強制的にロードしてそれを上書きするための不快なハッキング。

最終的に私はActiveSupportのto_jsonを完全にバイパスするために、次のコードを作成しました。 config/initializers/patches.rbに入れて、{}.jsonizeまたは[].jsonizeを使ってJSON文字列を生成することができます。何にも矛盾はなく、保証されています。コードの

# 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'が半解決の解決策であり、依然としていくつかのエンコーダを上書きする必要があるということです。 (WARNING:。MultiJsonを使用していますRailsの3.xの、のために、それは少なくともActiveSupport::JSON.backend = :json_gemでなければならない、またはそれは黙って無操作できなくなります)

私の場合、私は、JSONの宝石1.4のでString#to_jsonを上書きする必要がありました。 3は、ASCII以外の、しかし有効な-UTF8文字を盲目的に("\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を自由に使用している - -

は、ここで私が使用してきたモンキーパッチだ文字列、配列とハッシュ。

+0

これは、Rails 3.1.3で絵文字を修正するのに役立ちました。ありがとう。 – Chalkers

3

はしばらくの間、これを戦った後..私は最も簡単な解決策があることが判明:どこでもactivesupportの後にロードされ

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 

プット

...

関連する問題