2011-12-14 29 views
16

Tôi đang cố gắng gỡ lỗi một vấn đề trong đó Rails không giải mã dữ liệu JSON POST.Yêu cầu JSON đường ray không được phân tích cú pháp chính xác thành thông số bài đăng

Nhật ký máy chủ hiển thị:

2011-12-14T06:44:44+00:00 app[web.2]: Started POST 
2011-12-14T06:44:44+00:00 app[web.2]: Processing by PostsController#create as */* 
2011-12-14T06:44:44+00:00 app[web.2]: Parameters: {"{\"athlete_id\":\"\",\"known_as\":\"abc\",\"email\":\"[email protected]\",\"result\":\"112233\",\"rx\":false,\"mods\":\"thkjth\",\"notes\":\"\"}"=>nil, "affiliate_id"=>"testaffiliate", "wod_id"=>"12345"} 

Lưu ý rằng chuỗi JSON không được phân tích cú pháp - Rails được gán nó như là một then chốt trong việc băm, trỏ đến một giá trị nil. Có ai có bất kỳ ý tưởng trước khi tôi viết một before_filter cố gắng JSON.parse tất cả các phím params?

Tôi không nghĩ rằng điều này là có liên quan vì tôi đang gửi và nhận dữ liệu không sao, nhưng sự cố này xảy ra trong yêu cầu CORS từ IE (sử dụng XDomainRequest).

Trả lời

9
before_filter :fix_ie_params, only: [:create, :update] 

Đối Thin:

def fix_ie_params 
    if request.format == '*/*' 
    # try to JSON decode in case of IE XDR 
    begin 

     params.merge! ActiveSupport::JSON.decode(request.body.string) 

    rescue Exception=>e 
     # todo: log exception 
    end 
    end 
end 

Đối UnicornPhusion tải hành khách:

def fix_ie_params 
    if request.format == '*/*' 
    # try to JSON decode in case of IE XDR 
    begin 

     request.body.rewind 
     params.merge! ActiveSupport::JSON.decode(request.body.read) 

    rescue Exception=>e 
     # todo: log exception 
    end 
    end 
end 
+0

Tôi thấy rằng làm điều này (trên lân) Tôi cơ thể của yêu cầu bao gồm trong params như là một chìa khóa: '{'theBodyOfRequest' => nil,: controller => users,: action => 'update'}' Tùy thuộc vào trường hợp sử dụng của bạn có thể gây ra sự cố. Vì đó là tham số đầu tiên, tôi đã thêm 'params.shift' để xóa nó. – Peter

+0

@collin, vâng - Dữ liệu tôi đã POST ban đầu là JSON '{: foo =>" bar "}' (đã được xâu chuỗi để gửi) vì vậy các tham số tại bộ điều khiển trông giống như: '{" {\ "foo \" => \ "bar \"} => nil, "điều khiển" => "người dùng" ...} ' – Peter

+0

@Peter, có vẻ như vấn đề ban đầu tôi đã mô tả trong câu hỏi, phải không? Bạn có chắc chắn rằng bộ lọc của bạn đang được chạy? – colllin

16

Bạn có thể vượt qua điều này bằng cách đặt tiêu đề Kiểu nội dung thành "application/json". Bạn có thể cho phép trình điều khiển biết những gì nó mong đợi để trở về với tiêu đề Accept được thiết lập là "application/json".

Lệnh sau với cả hai tiêu đề:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Accept: application/json" --header "Content-Type: application/json" 

Tạo này trong các bản ghi:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:09:48 -0800 
    Processing by MyController#create as JSON 
    Parameters: {"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "wassup"=>{"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "controller"=>"wassup", "action"=>"create"}} 
Completed 200 OK in 5ms (Views: 2.0ms | ActiveRecord: 0.0ms) 

Lệnh này với tiêu đề Chấp nhận:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Accept: application/json" 

Tạo những nhật ký:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:07:26 -0800 
    Processing by MyController#create as JSON 
    Parameters: {"{ \"company\": { \"name\": \"acme\", \"address\": \"123 Carrot Street\" } }"=>nil} 
Completed 200 OK in 7ms (Views: 5.0ms | ActiveRecord: 0.0ms) 

Và cuối cùng lệnh này với Content-Type header:

curl -d '{ "company": { "name": "acme", "address": "123 Carrot Street" } }' http://0.0.0.0:3000/mysite --header "Content-Type: application/json" 

Tạo các bản ghi:

Started POST "/mysite" for 127.0.0.1 at 2012-01-11 16:08:11 -0800 
    Processing by MyController#create as */* 
    Parameters: {"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "wassup"=>{"company"=>{"name"=>"acme", "address"=>"123 Carrot Street"}, "controller"=>"wassup", "action"=>"create"}} 
Completed 200 OK in 4ms (Views: 2.0ms | ActiveRecord: 0.0ms) 

Thông báo các thông số phân tích cú pháp và thông điệp xử lý sự thay đổi một cách tinh tế với nhau loại tiêu đề.

+3

Cảm ơn rất nhiều cho câu trả lời của bạn! Thật không may, với XDomainRequest tôi không có quyền kiểm soát các tiêu đề. (Xem các mục 3 và 4 trong [bài viết này] (http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx).) Vì vậy, tôi nghĩ rằng đây có lẽ là câu trả lời đúng, nhưng không hoàn toàn giải quyết được vấn đề của tôi. Bạn có biết nếu có cách nào để nói cho bộ điều khiển giả sử mọi thứ là một yêu cầu JSON không? Hoặc ít nhất đặt loại nội dung mặc định thành JSON? – colllin

+1

Các json được phân tích cú pháp vào thành viên params (trong đường ray 3.1) trong params_parser.rb giữ ActionDispatch :: ParamsParser và là một phần của middleware. Bạn có thể thêm một phần khác của phần mềm trung gian để đưa vào kiểu yêu cầu đến và đặt nó một cách thích hợp. Tuy nhiên, nếu bạn định làm điều đó, bạn có thể chỉ cần đặt một số logic trong bộ điều khiển để làm điều đó cho mã cụ thể của bạn và không thay đổi phần còn lại của ngăn xếp trung gian. – Grant

Các vấn đề liên quan