code

Rails는 빈 어레이를 요청 매개 변수에서 nil로 변환합니다.

starcafe 2023. 2. 12. 18:04
반응형

Rails는 빈 어레이를 요청 매개 변수에서 nil로 변환합니다.

내 앱에 Backbone 모델이 있는데, 이것은 일반적인 평면 객체가 아니라 큰 중첩 객체이며 중첩된 부분을 MySQL 데이터베이스의 TEXT 열에 저장합니다.

Rails API에서 JSON 인코딩/디코딩을 처리하여 외부에서 이 큰 중첩된 JSON 오브젝트의 일부를 문자열화된 JSON 텍스트로 저장하더라도 POST/GET할 수 있도록 하고 싶었습니다.

그러나 Rails가 빈 어레이를 마법처럼 변환하는 문제가 발생했습니다.nil가치.예를 들어, 이것을 POST 했을 경우:

{
  name: "foo",
  surname: "bar",
  nested_json: {
    complicated: []
  }
}

Rails 컨트롤러에는 다음이 표시됩니다.

{
  :name => "foo",
  :surname => "bar",
  :nested_json => {
    :complicated => nil
  }
}

그래서 내 JSON 데이터가 변경되었어..

이 문제에 부딪힌 적이 있는 사람이 있습니까?Rails가 POST 데이터를 수정하는 이유는 무엇입니까?

갱신하다

다음은 고객이 수행하는 작업입니다.

https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/request.rb#L288

~이유는 다음과 같습니다.

https://github.com/rails/rails/pull/8862

이제 문제는 중첩된 JSON API 상황에서 이 문제를 어떻게 가장 잘 해결할 것인가 하는 것입니다.

여러 번 검색한 결과, Rails 4.1부터는 deep_munge "기능"을 완전히 생략할 수 있다는 것을 알게 되었습니다.

config.action_dispatch.perform_deep_munge = false

매뉴얼을 찾을 수 없습니다만, 이 옵션의 소개는 https://github.com/rails/rails/commit/e8572cf2f94872d81e7145da31d55c6e1b074247 에서 보실 수 있습니다.

https://groups.google.com/forum/#!topic/rubyonrails-security/t1WFuQyavI에 기재되어 있는 보안 위험이 있습니다.

이것은 이미 알려진 최근 도입된 문제인 것 같습니다.https://github.com/rails/rails/issues/8832

빈 어레이의 위치를 알고 있으면 언제든지params[:...][:...] ||= []이전 필터에 있습니다.

또는 BackBone 모델을 JSON 메서드로 변경하여 nested_json 값을 명시적으로 문자열화할 수 있습니다.JSON.stringify()게시하기 전에 수동으로 구문 분석하여 다시 출력합니다.JSON.parsebefore_filter로 설정합니다.

못생겼지만, 잘 될 거야

파라미터는 다음과 같이 자체 해석할 수 있습니다.

class ApiController
  before_filter :fix_json_params    # Rails 4 or earlier
  # before_action :fix_json_params  # Rails 5

  [...]

  protected

  def fix_json_params
    if request.content_type == "application/json"
      @reparsed_params = JSON.parse(request.body.string).with_indifferent_access
    end
  end

  private

  def params
    @reparsed_params || super
  end
end

이것은, JSON 컨텐츠 타입의 요구를 검색해, 요구 본문을 재파싱 해, 다음에 대행 수신하는 것으로 동작합니다.paramsmethod를 지정하면 재파손된 파라미터가 있는 경우 해당 파라미터를 반환합니다.

저도 비슷한 문제에 부딪혔어요.

빈 문자열을 배열의 일부로 전송하여 수정했습니다.

그래서 이상적으로 당신의 죄수들은

{
  name: "foo",
  surname: "bar",
  nested_json: {
    complicated: [""]
  }
}

따라서 빈 어레이를 보내는 대신 딥 멍깅 프로세스를 건너뛰기 위해 요청 시 항상("")을 전달합니다.

다음은 원시 요청 본문을 다시 파싱하지 않는 합리적인 해결책입니다.고객이 폼 데이터를 POST 하고 있는 경우는 동작하지 않는 경우가 있습니다만, 저는 JSON을 POST 하고 있습니다.

application_controller.rb:

  # replace nil child params with empty list so updates occur correctly
  def fix_empty_child_params resource, attrs
    attrs.each do |attr|
      params[resource][attr] = [] if params[resource].include? attr and params[resource][attr].nil?
    end
  end

그러면 컨트롤러에...

before_action :fix_empty_child_params, only: [:update]

def fix_empty_child_params
  super :user, [:child_ids, :foobar_ids]
end

에 POSTED가 POSTED가 .child_ids: [] ★★★★★★★★★★★★★★★★★」child_ids: nil그 업데이트는 "모든 아이들을 제거하라"는 의미였으면 합니다.가 「」를 .child_ids POST 는 안 됩니다.이, 「POST」는 「POST」라고 하는 것입니다.params[:resource].include? attr 되다false요청 파라미터는 변경되지 않습니다.

비슷한 문제가 발생했는데, 위에서 설명한 것처럼 빈 문자열로 어레이를 전달하면 Rails에 의해 올바르게 처리된다는 것을 알게 되었습니다.폼을 송신할 때에 이 문제가 발생했을 경우는, 어레이 파라메트와 일치하는 빈 숨김 필드를 포함할 수 있습니다.

<input type="hidden" name="model[attribute_ids][]"/>

실제 파라미터가 비어 있는 경우 컨트롤러는 항상 빈 문자열이 있는 어레이를 표시하므로 전송은 스테이트리스 상태로 유지됩니다.

언급URL : https://stackoverflow.com/questions/14647731/rails-converts-empty-arrays-into-nils-in-params-of-the-request

반응형