Question

Je suis perplexe à ce problème.

ActiveSupport::JSON définit to_json sur des objets divers de base et le fait de la gemme JSON. Cependant, la mise en œuvre n'est pas la même chose - la version ActiveSupport prend des arguments et la version gem JSON ne pas

.

J'ai installé un petit bijou qui exigeait la pierre précieuse JSON et mon application cassé. Le problème est que j'utilise to_json dans un contrôleur qui retourne une liste d'objets, mais je veux contrôler les attributs qui sont renvoyés.

Lorsque le code n'importe où dans mon système ne require 'json' je reçois ce message d'erreur:

TypeError: wrong argument type Hash (expected Data)

J'ai essayé quelques choses que je lis en ligne pour le corriger, mais rien ne fonctionnait. J'ai fini par réécrivant la gemme à utiliser ActiveSupport::JSON.decode au lieu de JSON.parse.

Cela fonctionne, mais ce n'est pas durable ... Je ne peux pas être des pierres précieuses qui bifurquent chaque fois que je veux utiliser un bijou qui nécessite la gemme JSON.

Mise à jour:. La meilleure solution de ce problème est de passer à Rails 2.3 ou supérieur, qui le fixe

Était-ce utile?

La solution

Mise à jour Ce correctif est uniquement applicable aux rails <2.3. Comme Giles mentionne ci-dessous, ils ont fixé cela à 2.3 en interne en utilisant la même technique. Mais méfiez-vous de la première pierre précieuse JSON tentative de compatibilité Rails (json/add/rails), qui, si nécessaire sera explicitement briser tout recommencer.

Voulez-vous dire la déclaration de require 'json' se pose cette exception? Ou voulez-vous dire lorsque vous appelez @something.to_json(:something => value) vous obtenez l'erreur? Ce dernier est ce que j'attendre, si vous avez un problème nécessitant la pierre précieuse JSON alors je ne suis pas sûr de ce qui se passe.

Je viens de rencontrer ce problème avec la gemme OAuth. Dans mon cas, il n'y a pas un vrai conflit, parce que la pierre précieuse oauth ne dépend pas de la mise en œuvre de to_json. Par conséquent, le problème est que JSON est en train d'écraser les déclarations de ActiveSupport. Je résolu ce problème en exigeant simplement JSON avant ActiveSupport est chargé. Mettre

require 'json'

à l'intérieur du Rails::Initializer a fait l'affaire (bien que le mettre après le bloc n'a pas).

Cela permet de ActiveSupport écraserait la mise en œuvre par défaut JSON au lieu.

Maintenant, si vous utilisez un bijou qui dépend en fait de la mise en œuvre de JSON to_json alors vous êtes un ruisseau. C'est sans aucun doute le pire des méta-programmation, et je défendre les rails et les développeurs de pierres précieuses JSON pour résoudre le conflit, mais il sera douloureux parce que l'un ou l'autre devra briser la rétrocompatibilité.

À court terme, les auteurs de pierres précieuses peuvent être en mesure de combler l'écart en soutenant les deux implémentations. Ceci est plus ou moins possible selon la façon dont la gemme utilise la méthode. Un scénario pire des cas est une fourchette officielle (ie. De gem et gem-rails).

Autres conseils

UPDATE : Même avec Rails 3.2, le même problème reste non fixé. Le hack méchant pour charger de force la pierre précieuse JSON et l'écraser, ce qui est.

Finalement, je me suis retrouvé avec le code suivant, pour contourner entièrement la to_json de ActiveSupport complètement. Mettez-le dans config/initializers/patches.rb, et vous pouvez faire {}.jsonize ou [].jsonize pour générer chaîne JSON. Aucun conflit avec quoi que ce soit, garanti.

# 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

Les 8 lignes de code font votre application 50 fois plus rapide pour l'encodage JSON. Probablement que vous voulez faire la même chose. :)


J'ai eu un problème similaire jusqu'à Rails 2.3.8.

Le problème est que ActiveSupport::JSON.backend = 'JSONGem' est une solution foireux et vous avez encore besoin d'écraser certains encodeurs vous-même. ( AVERTISSEMENT :. 3.x Rails, qui utilise MultiJson, il doit être ActiveSupport::JSON.backend = :json_gem au moins, ou il sera en silence no-op)

Dans mon cas, je devais remplacer String#to_json car joyau JSON 1.4.3 est mieux en ce qu'elle ne codait pas aveuglément des caractères non-ascii-mais-valid-UTF8 sous forme de "\uXXXX" où il n'est pas nécessaire, vous obtenir octets plus courts (bons pour la sérialisation) et des résultats faciles à lire ("日本語" ressemble beaucoup plus sexy à mes yeux que "\u65e5\u672c\u8a9e").

Voici le patch de singe que je me sers - mettre le code suivant dans 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

et vous êtes libre d'utiliser to_json sur quoi que ce soit -. Les chaînes, tableaux et Hash

Après avoir combattu pendant un certain temps .. Je trouve que la solution soit la plus simple:

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

mettre que partout après activesupport est chargé ..

Je suis sûr qu'ils ont réglé ça en 2.3 mais je ne me souviens pas comment.

Dans mon cas unique bien, j'ai eu un Ruby (non-rails) application qui a chargé en fait une application Rails (à partir d'une charge de config / environment.rb) ainsi que des pierres précieuses qui référençaient JSON. Cela m'a causé d'énormes maux de tête en raison du fait que je ne pouvais pas simplement modifier le fichier environment.rb de l'application Rails. J'ai fini par bifurquer un certain nombre de pierres précieuses afin d'obtenir JSON travailler sans élever la TypeError redoutée. Mauvais message type d'argument Hash (données attendues)

J'ai eu un peu de chance avec cette solution, ce qui est exactement le contraire que la réponse du wiki de la communauté ci-dessus ... http: // blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.html qui préconise essentiellement d'appeler require 'active_support' avant require 'json'

Ce fut la seule façon que je pouvais le faire fonctionner, et croyez-moi, j'ai tout essayé pendant plusieurs mois.

Je n'ai pas encore essayer, mais il semble que Rails 2.3.3 vous donne un certain contrôle:

ActiveSupport::JSON.backend = 'JSONGem'

trouvé

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top