Rails에서 to_json을 재정의하는 방법은 무엇입니까?


94

최신 정보:

이 문제는 제대로 조사되지 않았습니다. 진짜 문제는 render :json.

원래 질문의 첫 번째 코드 붙여 넣기는 예상 결과를 산출합니다. 그러나 여전히 경고가 있습니다. 이 예를 참조하십시오.

render :json => current_user

이다 NOT 과 동일

render :json => current_user.to_json

즉 , User 개체와 연결된 메서드를 render :json자동으로 호출하지 않습니다 to_json. 실제로 모델에서 to_json재정의되는 경우 아래 에 설명 된 내용이 생성 됩니다.Userrender :json => @userArgumentError

요약

# works if User#to_json is not overridden
render :json => current_user

# If User#to_json is overridden, User requires explicit call
render :json => current_user.to_json

이 모든 것이 나에게는 어리석은 것 같습니다. 이것은 유형 이 지정 될 때 render실제로 호출되지 않는다는 것을 알려주는 것 같습니다 . 누군가 여기서 실제로 무슨 일이 일어나고 있는지 설명 할 수 있습니까?Model#to_json:json

이 문제를 해결할 수있는 모든 genii는 다른 질문에 답할 수 있습니다. Rails에서 @ foo.to_json (options) 및 @ bars.to_json (options)을 결합하여 JSON 응답을 빌드하는 방법


원래 질문 :

나는 다른 몇 가지 예를 보았지만 내가 찾고있는 것을하지 않습니다.

노력하고있어:

class User < ActiveRecord::Base

  # this actually works! (see update summary above)
  def to_json
    super(:only => :username, :methods => [:foo, :bar])
  end

end

나는 얻고 ArgumentError: wrong number of arguments (1 for 0)에서

/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json

어떤 아이디어?


귀하의 예제는 내 모델 중 하나에서 작동합니다. 의 어떤은 수행 username, foo또는 bar방법은 인수를 기대?
— Jonathan Julian

아니, username방법 및되지 않습니다 foo및 bar방법을 필요로하지 않는다. 오류가 발생한 위치를 표시하기 위해 질문을 업데이트했습니다.
— maček 2010

1.8.7을 실행하고 있습니다. 해당 파일을 열고 인수가 0 인 메서드에 인수를 전달하는 이유를 확인해야합니다.
— Jonathan Julian

답변:


214

하나의 매개 변수 인 해시 로 재정의해야하기 ArgumentError: wrong number of arguments (1 for 0)때문에 얻는 to_json것 options입니다.

def to_json(options)
  ...
end

의 긴 설명 to_json, as_json및 렌더링 :

ActiveSupport 2.3.3에서는 as_json발생한 문제와 같은 문제를 해결하기 위해 추가되었습니다. json 의 생성 은 json의 렌더링 과 분리되어야합니다 .

이제 언제든지 to_json객체에서 as_json호출되고 데이터 구조를 생성하기 위해 호출 된 다음 해당 해시는를 사용하여 JSON 문자열로 인코딩됩니다 ActiveSupport::json.encode. 이것은 객체, 숫자, 날짜, 문자열 등 모든 유형에 대해 발생합니다 (ActiveSupport 코드 참조).

ActiveRecord 개체는 동일한 방식으로 작동합니다. as_json모든 모델의 속성을 포함하는 해시를 생성 하는 기본 구현이 있습니다. 원하는 JSON 구조를 생성하려면 모델에서 재정의해야합니다as_json . as_jsonold와 마찬가지로 to_json는 선언적으로 포함 할 속성과 메서드를 지정할 수있는 옵션 해시를 사용합니다.

def as_json(options)
  # this example ignores the user's options
  super(:only => [:email, :handle])
end

컨트롤러에서 render :json => o문자열 또는 개체를받을 수 있습니다. 문자열 인 경우 응답 본문 (객체 인 경우) to_json이 호출 될 때 전달 as_json되며 위에서 설명한대로 트리거 됩니다.

따라서 모델이 as_json재정의 (또는 그렇지 않은 경우) 로 올바르게 표현되는 한 , 하나의 모델을 표시하는 컨트롤러 코드는 다음과 같아야합니다.

format.json { render :json => @user }

이야기의 교훈은 다음과 같습니다. 직접 전화하지 말고 그렇게 to_json하도록 허용 하십시오 render. JSON 출력을 조정해야하는 경우 as_json.

format.json { render :json => 
    @user.as_json(:only => [:username], :methods => [:avatar]) }

@Jonathan Julian, 이것은에 대한 매우 유용한 설명입니다 as_json. ActiveRecord :: Serialization 문서 ( api.rubyonrails.org/classes/ActiveRecord/… ) 에서 볼 수 있듯이 이에 대한 문서 는 거의 없습니다. 나는 이것을 시도 할 것입니다 :)
— maček

1
@Jonathan Julian, 제가 이것을 10 번 찬성 할 수 있다면 그렇게 할 것입니다. 도대체 as_json문서 는 어디에 ! 다시 한 번 감사드립니다 :)
— maček 2010

71

당신이 레일 3에서이 문제가 발생하는 경우, 오버라이드 (override) serializable_hash대신 as_json. 이렇게하면 XML 서식도 무료로 제공됩니다. :)

이것은 알아내는 데 영원히 걸렸습니다. 누군가에게 도움이되기를 바랍니다.


1
누구든지 방법에 대한 좋은 글을 알고 serializable_hash있습니까? 내가 그것을 사용할 때, 그것은 대신에 항상 "<hash>"로 그것을 감싸도록 객체를 그 이름으로 감싸는 것에서 내 후속 xml 출력을 변경한다 (예를 들어, 인용 객체의 경우 "quote").
— Tyler Collier

@TylerCollier 같은 옵션이어야합니다to_xml
— Sam Soffes

이 솔루션에 감사드립니다! 나는 ruby2 / rails4를 사용하고 있고 as_json은 중첩 된 객체로 작업하지 않았고, 재정의 된 메서드는 'include'에서 호출되지 않았으며 serializable_hash가 작동합니다!
— santuxus

serializable_hash를 대신 대체해야하는 이유에 대한 설명은 robots.thoughtbot.com/better-serialization-less-as-json 을 참조하십시오 .
— Topher Hunt

36

사용자 옵션을 무시하지 않고 옵션을 추가하고 싶지 않은 사람들을 위해 :

def as_json(options)
  # this example DOES NOT ignore the user's options
  super({:only => [:email, :handle]}.merge(options))
end

이것이 누구에게나 도움이되기를 바랍니다 :)


1
나는 기본을 제외하고 이것은 내가 그것을 할 방법이다 options와 해시 = {}가 호출 필요하지 그래서
— mroach을

4

to_json이 아니라 as_json을 재정의하십시오. 그리고 as_json에서 원하는 것을 호출하십시오.

이 시도:

def as_json 
 { :username => username, :foo => foo, :bar => bar }
end

아닌가요 as_json단지 ActiveResource을 위해?
— Jonathan Julian

분명히 ActiveRecord :: Serialization에는 as_json api.rubyonrails.org/classes/ActiveRecord/Serialization.html
— glebm 2010

@glebm, 나는 이것을 시도했고 동일한 결과를 얻고 있습니다. 당신에게 보여주기 위해 내 질문을 업데이트했습니다.
— maček 2010

@glebm, 여전히 똑같은 오류가 발생합니다. 내가 할 때에도 render :json => current_user예상되는 기본 결과 ( UserJSON 형식의 모델에 대한 모든 속성)를 얻습니다 . 모델에 as_json메서드를 추가하고 User동일한 작업을 시도하면 오류가 발생합니다. (
— maček

@glebm, 감사합니다. 내가 뭔가 잘못하고 있다는 것을 알고 있습니다. 업데이트 된 질문을 확인하는 것이 좋습니다.
— maček 2010
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.