Как вы справляетесь с конфликтом между ActiveSupport::JSON и драгоценным камнем JSON?

StackOverflow https://stackoverflow.com/questions/683989

Вопрос

Я в тупике с этой проблемой.

ActiveSupport::JSON определяет to_json на различных основных объектах, как и на драгоценном камне JSON.Однако реализация отличается - версия ActiveSupport принимает аргументы, а версия JSON gem - нет.

Я установил драгоценный камень, для которого требовался драгоценный камень JSON, и мое приложение сломалось.Проблема в том, что я использую to_json в контроллере, который возвращает список объектов, но я хочу контролировать, какие атрибуты возвращаются.

Когда код в любом месте моей системы выполняет require 'json' Я получаю это сообщение об ошибке:

TypeError: wrong argument type Hash (expected Data)

Я попробовал пару вещей, которые прочитал в Интернете, чтобы исправить это, но ничего не сработало.В итоге я переписал драгоценный камень, чтобы использовать ActiveSupport::JSON.decode вместо того , чтобы JSON.parse.

Это работает, но это ненадежно...Я не могу разветвлять драгоценные камни каждый раз, когда хочу использовать драгоценный камень, для которого требуется драгоценный камень JSON.

Обновить: Лучшим решением этой проблемы является обновление до Rails 2.3 или выше, которое исправило ее.

Это было полезно?

Решение

Обновить Это исправление применимо только к Rails < 2.3.Как упоминает Джайлс ниже, они исправили это в версии 2.3 внутренне, используя почти ту же технику.Но остерегайтесь более ранней попытки json gem обеспечить совместимость с Rails (json/add/rails), который, если потребуется явно, сломает все заново.

Вы имеете в виду require 'json' само утверждение вызывает это Исключение?Или ты имеешь в виду, когда ты звонишь @something.to_json(:something => value) вы получаете сообщение об ошибке?Последнее - это то, чего я бы ожидал, если у вас возникла проблема, требующая JSON gem, то я не уверен, что происходит.

Я только что столкнулся с этой проблемой с драгоценным камнем oauth.В моем случае истинного конфликта нет, потому что gem oauth не зависит от to_json реализация.Следовательно, проблема заключается в том, что JSON блокирует объявления ActiveSupport .Я решил это, просто потребовав json перед загрузкой ActiveSupport.Помещая

require 'json'

внутри Rails::Initializer сделал свое дело (хотя поместил его после блока НЕ сделал).

Это позволяет ActiveSupport вместо этого блокировать реализацию JSON по умолчанию.

Теперь, если вы используете драгоценный камень, который на самом деле зависит от реализации JSON to_json тогда вы находитесь в затруднительном положении.Это определенно худшее из метапрограммирования, и я бы посоветовал разработчикам Rails и JSON gem разрешить конфликт, хотя это будет болезненно, потому что одному или другому придется нарушить обратную совместимость.

В краткосрочной перспективе авторы gem, возможно, смогут восполнить пробел, поддержав обе реализации.Это более или менее выполнимо в зависимости от того, как драгоценный камень использует этот метод.Наихудший сценарий - это официальный форк (т.е. gem и gem-rails).

Другие советы

Обновить:Даже с Rails 3.2 та же проблема остается не устраненной.Отвратительный взлом, чтобы принудительно загрузить драгоценный камень json и перезаписать его, то есть.

В конце концов я пришел к следующему коду, чтобы полностью обойти activesupport's 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 строк кода создают ваше приложение 50 раз быстрее для кодирования в формате JSON.Вероятно, вы хотите сделать то же самое.:)


У меня была похожая проблема вплоть до версии Rails 2.3.8.

Проблема в том, что ActiveSupport::JSON.backend = 'JSONGem' это половинчатое решение, и вам все равно нужно перезаписать некоторые кодировщики самостоятельно.(ПРЕДУПРЕЖДЕНИЕ:для Rails 3.x, который использует MultiJson, он должен быть ActiveSupport::JSON.backend = :json_gem по крайней мере, иначе это будет молчаливый отказ от операции.)

В моем случае мне нужно было перезаписать String#to_json потому что JSON gem 1.4.3 лучше в том смысле, что он не кодирует вслепую символы, отличные от ascii, но допустимые UTF8, в виде "\uXXXX" там, где в этом нет необходимости, так что вы получаете более короткие байты (хорошо для сериализации) и удобные для чтения результаты ("日本語" на мой взгляд, выглядит намного сексуальнее, чем "\u65e5\u672c\u8a9e").

Вот патч monkey, который я использовал - вставьте следующий код в 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 на чем угодно - строке, массиве и хэше.

После того, как некоторое время боролся с этим..Я нашел самое простое решение, которое должно быть:

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..

Я почти уверен, что они исправили это в версии 2.3, но я не могу вспомнить как.

В моем, хотя и уникальном случае, у меня было приложение Ruby (не rails), которое фактически загружало приложение Rails (из config / environment.rb load), а также некоторые драгоценные камни, которые ссылались на json.Это вызвало у меня огромную головную боль из-за того, что я не мог просто изменить файл environment.rb приложения Rails.В итоге я разветвил несколько драгоценных камней, чтобы заставить json работать, не вызывая страшного TypeError:сообщение о хэше неправильного типа аргумента (ожидаемые данные).

Мне немного повезло с этим решением, которое прямо противоположно ответу сообщества wiki выше...http://blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.html который в основном выступает за вызов требуется 'active_support' ДО ТОГО , КАК требовать 'json'

Это был единственный способ заставить это работать, и, поверьте мне, я перепробовал все на протяжении многих месяцев.

Мне еще предстоит попробовать это, но, похоже, Rails 2.3.3 дает вам некоторый контроль:

ActiveSupport::JSON.backend = 'JSONGem'

Найдено здесь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top