Pregunta

Estoy confundido con este problema.

ActiveSupport::JSON define to_json en varios objetos básicos y también lo hace la gema JSON. Sin embargo, la aplicación no es lo mismo - la versión ActiveSupport toma argumentos y la versión JSON Gem no

.

He instalado una joya que requiere la gema JSON y se rompió mi aplicación. La cuestión es que estoy usando to_json en un controlador que devuelve una lista de objetos, pero yo quiero para controlar qué atributos son devueltos.

Cuando el código en cualquier parte de mi sistema no require 'json' me sale este mensaje de error:

TypeError: wrong argument type Hash (expected Data)

He intentado un par de cosas que he leído en línea para solucionarlo, pero nada funcionó. Terminé re-escritura de la gema para usar en lugar de ActiveSupport::JSON.decode JSON.parse.

Esto funciona, pero no es sostenible ... No puedo ser que se bifurcan gemas cada vez que quiero usar una joya que requiere la gema JSON.

Actualización:. La mejor solución de este problema es actualizar a Rails 2.3 o superior, que arreglan el fallo

¿Fue útil?

Solución

Actualizar Esta solución sólo es aplicable a los carriles <2,3. Como se menciona más adelante Giles, que arreglaron esto en 2.3 internamente utilizando la misma técnica. Pero cuidado intento anterior de la gema JSON en rieles compatibilidad (json/add/rails), , que, si se requiere explícitamente se romperá todo de nuevo.

¿Se refiere a la declaración require 'json' sí plantea esa excepción? ¿O quiere decir cuando se llama @something.to_json(:something => value) se obtiene el error? Esto último es lo que se espera, si usted tiene un problema que requiere la gema JSON entonces no estoy seguro de lo que está pasando.

Me acabo de encontrar con este problema con la gema oauth. En mi caso, no hay un verdadero conflicto, porque la joya oauth no depende de la aplicación to_json. Por lo tanto, el problema es que JSON se clobbering las declaraciones ActiveSupport. He resuelto esto simplemente requiere JSON antes de cargar ActiveSupport. Poniendo

require 'json'

Dentro de la Rails::Initializer hizo el truco (aunque ponerlo después del bloque no lo hizo).

Esto permite ActiveSupport a darle una paliza a la aplicación por defecto en lugar de JSON.

Ahora bien, si está utilizando una joya que realmente depende de la implementación JSON de to_json entonces está un arroyo. Este es sin duda el peor de los meta-programación, y yo estaría a favor de los rieles y los desarrolladores de la gema JSON para resolver el conflicto, aunque será doloroso porque uno o el otro tendrá que romper la compatibilidad hacia atrás.

A corto plazo, los autores de la gema puede ser capaz de cerrar la brecha mediante el apoyo a ambas implementaciones. Esto es más o menos factible en función de cómo la gema utiliza el método. A peor de los casos es un tenedor oficial (es decir. gem y gem-rails).

Otros consejos

Actualizar : Incluso con Rails 3.2, el mismo problema permanece sin fijar. El truco desagradable para cargar la fuerza a la gema JSON y reescribir, es decir.

Finalmente terminé con el siguiente código, de pasar por alto por completo to_json de ActiveSupport por completo. Ponerlo en config/initializers/patches.rb, y se puede hacer {}.jsonize o [].jsonize para generar cadena JSON. No hay conflictos con cualquier cosa, garantizado.

# 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

Las 8 líneas de código hacen que su aplicación 50 veces más rápido para JSON codificación. Probablemente usted quiere hacer lo mismo. :)


He tenido un problema similar hasta Rails 2.3.8.

El problema es que ActiveSupport::JSON.backend = 'JSONGem' es una solución a medias y todavía se necesita para sobrescribir algunos codificadores mismo. ( Advertencia :. Para rieles 3.x, que utiliza MultiJson, se debe ActiveSupport::JSON.backend = :json_gem al menos, o será en silencio no-op)

En mi caso, necesitaba para sobrescribir String#to_json porque JSON joya 1.4.3 es mejor, ya que no codifica ciegas no-ascii-pero-valid-UTF8 caracteres en forma de "\uXXXX" donde no es necesario, por lo que obtener bytes más cortos (buenos para la serialización) y fáciles de leer los resultados ("日本語" se ve mucho más atractivo a los ojos de "\u65e5\u672c\u8a9e").

Aquí está el parche mono que he estado usando - poner el siguiente código en 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

y usted es libre de usar to_json en cualquier cosa -. Cuerdas, matriz y Hash

Después de luchar contra esto durante un tiempo .. He encontrado la solución más simple 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

puesto que en cualquier lugar, después de cargar ActiveSupport ..

Estoy bastante seguro de que lo arreglaron esto en 2.3, pero no puedo recordar cómo.

En mi caso único no obstante, que tenía un (no-rieles) aplicación Ruby que carga realmente una aplicación Rails (de una carga config / environment.rb), así como algunas joyas que hacían referencia a JSON. Esto me causó enormes dolores de cabeza debido al hecho de que no podía simplemente altera el archivo environment.rb de los rieles de aplicación. Terminé bifurcar una serie de gemas con el fin de obtener JSON para trabajar sin levantar la temida TypeError:. Hash tipo de argumento equivocado (que se espera de datos) mensaje

Yo tenía un poco de suerte con esta solución, que es exactamente lo contrario ya que la respuesta de la comunidad wiki por encima de ... http: // blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.html que básicamente aboga por llamar require 'active_support' antes require 'json'

Esta era la única manera de que pudiera hacer que funcione, y creen que me he intentado todo lo largo de muchos meses.

todavía tengo que probarlo, pero parece que los carriles 2.3.3 le da cierto control:

ActiveSupport::JSON.backend = 'JSONGem'

Encontrado aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top