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.parse
before_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 컨텐츠 타입의 요구를 검색해, 요구 본문을 재파싱 해, 다음에 대행 수신하는 것으로 동작합니다.params
method를 지정하면 재파손된 파라미터가 있는 경우 해당 파라미터를 반환합니다.
저도 비슷한 문제에 부딪혔어요.
빈 문자열을 배열의 일부로 전송하여 수정했습니다.
그래서 이상적으로 당신의 죄수들은
{
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
'code' 카테고리의 다른 글
잭슨이 Spring Boot에서 ZonedDateTime을 잘못 시리얼화함 (0) | 2023.02.12 |
---|---|
스프링 부트 1.3.0M1에서1.3.0으로 전환 시 "NoClassDefFoundError: GenericApplicationListener"M2 (0) | 2023.02.12 |
AngularJS: 컨트롤러에서 해결 기능을 사용할 경우 최소화할 수 있는 구문 수정 (0) | 2023.02.12 |
JSON이 JSONObject인지 JSONArray인지를 확인합니다. (0) | 2023.02.12 |
ID별 Woocommerce 제품 값 가져오기 (0) | 2023.02.12 |