Pergunta

Estou perplexo com este problema.

ActiveSupport::JSON define to_json em vários objetos do núcleo e assim que faz a jóia JSON. No entanto, a implementação não é o mesmo - a versão ActiveSupport leva argumentos ea versão JSON gem não

.

Eu instalei uma jóia que exigiu a jóia JSON e meu aplicativo quebrou. A questão é que eu estou usando to_json em um controlador que retorna uma lista de objetos, mas eu quero controlar quais atributos são devolvidos.

Quando qualquer código no meu sistema não require 'json' eu recebo essa mensagem de erro:

TypeError: wrong argument type Hash (expected Data)

Eu tentei um par de coisas que eu li online para corrigi-lo, mas nada funcionou. Acabei re-escrever o gem ao uso ActiveSupport::JSON.decode vez de JSON.parse.

Isso funciona, mas não é sustentável ... Eu não pode ser bifurcação gemas cada vez que eu quiser usar uma jóia que requer a gema JSON.

Update:. A melhor solução para este problema é atualizar para Rails 2.3 ou superior, que fixa-lo

Foi útil?

Solução

Atualizar Esta correção só é aplicável a Rails <2.3. Como Giles menciona abaixo, que fixa esta em 2,3 usando internamente muito a mesma técnica. Mas cuidado tentativa anterior do gem json no Rails compatibilidade (json/add/rails), que, se necessário explicitamente vai quebrar tudo de novo.

Você quer dizer a afirmação require 'json'-se levanta essa exceção? Ou você quer dizer quando você chamar @something.to_json(:something => value) você obter o erro? O último é o que eu esperaria, se você tem um problema que requer a gema JSON, então eu não sei o que está acontecendo.

Eu apenas corri para este problema com a gema OAuth. No meu caso, não há um verdadeiro conflito, porque a jóia OAuth não depende de implementação to_json. Portanto, o problema é que JSON é sobrepor as declarações ActiveSupport. Eu resolvi isso simplesmente exigindo json antes ActiveSupport é carregado. Colocar

require 'json'

dentro do Rails::Initializer fez o truque (embora colocando-o após o bloco não).

Isso permite ActiveSupport para espancar a implementação JSON padrão em vez.

Agora, se você estiver usando uma jóia que realmente depende da implementação JSON de to_json então você está até um riacho. Este é definitivamente o pior de meta-programação, e eu gostaria de defender os Rails e desenvolvedores gem JSON para resolver o conflito, embora seja doloroso, porque um ou outro terá que quebrar compatibilidade com versões anteriores.

No curto prazo, os autores gema pode ser capaz de preencher a lacuna, apoiando ambas as implementações. Isso é mais ou menos viável dependendo de como a jóia usa o método. A pior cenário é um fork oficial (ie. gem e gem-rails).

Outras dicas

Atualizar : Mesmo com Rails 3.2, o mesmo problema permanece sem conserto. O hack desagradável para forçar carregar o gem json e substituí-lo, isso é.

Eventualmente acabei com o seguinte código, a inteiramente desvio to_json do ActiveSupport completamente. Coloque-o em config/initializers/patches.rb, e você pode fazer {}.jsonize ou [].jsonize para gerar string JSON. Não há conflitos com qualquer coisa, garantida.

# 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

Os 8 linhas de código tornar seu aplicativo 50 vezes mais rápido para a codificação JSON. Provavelmente você quer fazer o mesmo. :)


Eu tenho tido um problema semelhante até Rails 2.3.8.

O problema é que ActiveSupport::JSON.backend = 'JSONGem' é uma solução assed metade e você ainda precisa substituir alguns codificadores de si mesmo. ( AVISO :. Para Rails 3.x, que usa MultiJson, deve ser ActiveSupport::JSON.backend = :json_gem, pelo menos, ou será silenciosamente não-op)

No meu caso, eu precisava String#to_json de substituição porque JSON gem 1.4.3 é melhor na medida em que não cegamente codificar caracteres não-ascii-mas-valid-UTF8 na forma de "\uXXXX" onde não é necessário, para que você obter bytes mais curtos (bom para serialização) e fácil de ler resultados ("日本語" parece muito mais sexy aos meus olhos do que "\u65e5\u672c\u8a9e").

Aqui está o patch macaco que eu tenho usado - coloque o seguinte código no 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

E você é livre para usar to_json em qualquer coisa -. String, array e hash

Depois de lutar contra isso por um tempo .. Eu encontrei a solução mais simples para ser:

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

colocar isso em qualquer lugar depois ActiveSupport é carregado ..

Eu tenho certeza que eles consertaram isso em 2.3, mas não me lembro como.

Na minha embora caso único, eu tinha uma (não-rails) aplicativo Ruby que realmente carregado uma aplicação Rails (a partir de um / carga configuração environment.rb), bem como algumas jóias que json referenciados. Isso me causou enormes dores de cabeça devido ao fato de que eu não poderia simplesmente alterar environment.rb da aplicação Rails. Acabei bifurcação um número de pedras preciosas a fim de obter json ao trabalho sem aumentar o TypeError temido:. Errado tipo de argumento Hash (esperado Dados) Mensagem

Eu tive um pouco de sorte com esta solução, que é exatamente o oposto como a resposta da comunidade wiki acima ... http: // blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.html que basicamente defende chamando require 'active_support' ANTES require 'json'

Esta foi a única maneira que eu poderia fazê-lo funcionar, e acreditem, eu tentei de tudo ao longo de muitos meses.

Eu ainda tenho que tentar, mas parece que Rails 2.3.3 dá-lhe algum controle:

ActiveSupport::JSON.backend = 'JSONGem'

Encontrada aqui

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top