2009-03-25 5 views
12

나는이 문제로 어려움을 겪고있다.ActiveSupport :: JSON과 JSON gem 사이의 충돌을 어떻게 처리합니까?

ActiveSupport::JSON은 다양한 핵심 개체에 대해 to_json을 정의하고 JSON 젬도 정의합니다. 그러나 구현은 동일하지 않습니다. ActiveSupport 버전에는 인수가 사용되며 JSON 젬 버전에는 인수가 없습니다.

JSON 보석이 필요하고 내 앱이 고장난 보석을 설치했습니다. 문제는 내가 개체 목록을 반환하는 컨트롤러에서 to_json을 사용하고 있지만 반환되는 특성을 제어하려고합니다.

TypeError: wrong argument type Hash (expected Data)

가 내가 그것을 해결하기 위해 온라인으로 읽을 몇 가지를 시도했지만 아무 일하지 : 코드 어디 내 시스템에서 require 'json'을 수행 할 때

는이 오류 메시지가 표시됩니다. 나는 JSON.parse 대신 ActiveSupport::JSON.decode을 사용하여 보석을 다시 쓰는 것을 끝내었다.

이 방법은 효과가 있지만 지속 가능하지 않습니다 ... JSON 보석이 필요한 보석을 사용할 때마다 보석을 포크로 찍을 수는 없습니다.

업데이트 :이 문제의 가장 좋은 해결책은 해결 된 레일즈 2.3 이상으로 업그레이드하는 것입니다.

+1

왜이 질문은 "커뮤니티 위키"로 표시됩니다? –

+0

나는 잘 모르겠다. 나는 그걸 시도하고 그것이 무엇을하는지 알게되었다. –

+0

나는 당신의 고통을 느꼈다. 나는이 엉망이 언젠가 정렬되기를 바란다. – MatthewFord

답변

2

업데이트이 수정은 레일 <에만 적용됩니다. Giles가 아래에서 언급했듯이, 그들은 2.3에서 이것을 거의 같은 기술을 사용하여 내부적으로 고쳤습니다. 그러나 레일스 호환성 (json/add/rails), 에서의 json gem의 이전 시도를 조심하십시오. 명시 적으로 필요하다면 다시 모든 것을 망칠 것입니다.

require 'json' 명세서 자체가 예외를 발생시키는 것을 의미합니까? 아니면 @something.to_json(:something => value)으로 전화하면 오류가 발생합니까? 후자는 내가 기대하는 것입니다. JSON 보석을 요구하는 문제가있는 경우 어떻게되는지 잘 모르겠습니다.

나는 oauth gem으로이 문제에 봉착했다. 내 경우에는 oauth gem이 to_json 구현에 의존하지 않기 때문에 진정한 충돌은 없습니다. 따라서 문제는 JSON이 ActiveSupport 선언을 파괴하고 있다는 것입니다. 필자는 ActiveSupport가로드되기 전에 단순히 json을 요구함으로써이를 해결했습니다. (블록이있었습니다을 넣어 불구하고)이 Rails::Initializer 내부

require 'json' 

가 속임수를 썼는지 퍼팅.

이렇게하면 ActiveSupport가 기본 JSON 구현을 대신 망칠 수 있습니다.

이제는 실제로 JSON 구현 to_json에 의존하는 보석을 사용하는 경우 크릭을 시작합니다. 이것은 분명히 최악의 메타 프로그래밍이며, Rails와 JSON gem 개발자가 충돌을 해결할 것을지지하지만, 다른 개발자가 이전 버전과의 호환성을 깨뜨려야하기 때문에 고통 스러울 것입니다.

단기간에 보석 제작자는 두 가지 구현을 모두 지원하여 차이를 극복 할 수 있습니다. 이것은 보석이 방법을 사용하는 방법에 따라 다소 가능합니다. 최악의 시나리오는 공식 포크 (즉, gemgem-rails)입니다.

+0

그래, 나는 'json'을 요구하는 호출을 사용할 때 to_json의 레일스 버전을 날려 버리며 많은 고통을 초래한다는 것을 의미한다. 제안 해 주셔서 감사합니다. require 'json/add/rails'를 사용하는 것이 좋습니다. 나는 그것을 일하게 할 수 없다. –

+0

은 처음 호출 할 때만 작동하므로, Rails 버전이로드되기 전에 호출하면 플러그인에서 필요로 할 때 아무 것도하지 않습니다. 실제로이 점을 Rails :: Initializer 블록에 넣었습니다. json/add/rails 일은 잘 모르겠지만 필요 없다고 생각합니다. – gtd

0

나는 2.3에서 이것을 고정시킬 것이라고 확신하지만 어떻게 기억할 수는 없다.

+0

그래, 나는 그들이 to_json을 직접 호출하지 않았다고 생각해. 대신 as_json을 정의하거나 JSON.generate 또는 ActiveSupport :: JSON.encode를 직접 호출합니다. 새로운 JSON 백엔드를 사용하면 ActiveSupport :: JSON.encode에서 원하는 라이브러리를 사용할 것으로 생각됩니다. –

0

나는 그것을 아직 시도했습니다,하지만 2.3.3은 몇 가지를 제어 할 수 레일과 같다 : 비 (독특한 케이스이기는하지만, 나는 루비를 가지고 내에서

ActiveSupport::JSON.backend = 'JSONGem' 

Found here

+0

예, Rails 2.3 이상에서이 문제를 해결합니다. –

0

을 rails) app (실제로 config/environment.rb로드에서)뿐만 아니라 json을 참조한 일부 보석을로드했습니다. 이로 인해 Rails 응용 프로그램의 environment.rb 파일을 단순히 변경하지 못했기 때문에 큰 두통을 낳았습니다. json이 무서운 TypeError : 잘못된 인수 유형 인 Hash (예상 데이터) 메시지를 발생시키지 않고 작동하도록하기 위해 많은 보석을 만들었습니다.

나는 기본적으로 는 'JSON'

을 필요로하기 전에 가 'active_support' 을 필요로 호출 옹호 위의 커뮤니티 위키의 대답과 정확히 반대되는이 솔루션과 약간의 행운이 ... http://blog.swivel.com/code/2009/03/active-support-and-json-gems-dont-play-nice.html 했다

이것이 내가 작동하게 할 수있는 유일한 방법이었고, 여러 달 동안 모든 것을 시도해 보았습니다.

18

업데이트 : 레일즈 3.2에서도 동일한 문제가 수정되지 않았습니다. 강제로 json gem을로드하고 덮어 쓰는 불쾌한 해킹입니다.

결국 나는 완전히 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 배 속도를 확인합니다. 아마도 당신은 똑같이하고 싶을 것입니다. :)


레일즈 2.3.8까지 비슷한 문제가있었습니다.

문제는 ActiveSupport::JSON.backend = 'JSONGem'이 절반 해결책이며 여전히 일부 인코더를 덮어 쓸 필요가 있다는 것입니다. (은 경고 :. MultiJson를 사용하여 레일 3.x를 들어, 적어도 ActiveSupport::JSON.backend = :json_gem해야하거나 조용히 어떤 조합 수 없습니다) 내 경우

, 나는 때문에 JSON 보석 1.4 String#to_json을 덮어 쓸 필요가 있었다. 3은 쓸데없는 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 

넣어

..

관련 문제