Hiển thị JSON trong bộ điều khiển


103

Tôi đang đọc một cuốn sách và trong một chương về Bộ điều khiển khi nó nói về công cụ kết xuất, đối với JSON, nó có một ví dụ như thế này nhưng không đi vào chi tiết nên tôi không thể tìm ra bức tranh lớn hơn mà ví dụ này phù hợp:

render :json => @projects, :include => tasks

Và cũng có một số ví dụ với JSONP sử dụng nó với các hàm gọi lại:

render :json => @record, :callback => 'updateRecordDisplay'

Ai đó có thể giải thích những điều này?

Câu trả lời:


127

Thông thường bạn sẽ trả lại JSON vì:

A) Bạn đang xây dựng một phần / tất cả ứng dụng của mình dưới dạng Ứng dụng Trang Đơn (SPA) và bạn cần JavaScript phía máy khách để có thể lấy thêm dữ liệu mà không cần tải lại đầy đủ trang.

hoặc là

B) Bạn đang xây dựng một API mà các bên thứ ba sẽ sử dụng và bạn đã quyết định sử dụng JSON để tuần tự hóa dữ liệu của mình.

Hoặc, có thể, bạn đang ăn thức ăn cho chó của riêng mình và làm cả hai

Trong cả hai trường hợp, render :json => some_datasẽ JSON-ify dữ liệu được cung cấp. Các :callbackchìa khóa trong ví dụ thứ hai cần giải thích thêm một chút (xem dưới đây), nhưng nó là một biến thể của ý tưởng tương tự (trở về dữ liệu trong một cách mà JavaScript có thể dễ dàng xử lý.)

Tại sao :callback?

JSONP (ví dụ thứ hai) là một cách để vượt qua Chính sách nguồn gốc giống nhau , là một phần của bảo mật tích hợp sẵn của mọi trình duyệt. Nếu bạn có API của mình tại api.yoursite.comvà bạn sẽ phân phát ứng dụng của services.yoursite.commình ngoài JavaScript của bạn, thì (theo mặc định) sẽ không thể (theo mặc định) có thể thực hiện XMLHttpRequestcác yêu cầu (XHR - hay còn gọi là ajax) từ servicestới api. Cách mà mọi người đã lén lút giải quyết hạn chế đó (trước khi thông số Chia sẻ tài nguyên nhiều nguồn gốc được hoàn thiện ) là gửi dữ liệu JSON từ máy chủ như thể nó là JavaScript thay vì JSON ). Do đó, thay vì gửi lại:

{"name": "John", "age": 45}

thay vào đó máy chủ sẽ gửi lại:

valueOfCallbackHere({"name": "John", "age": 45})

Do đó, ứng dụng JS phía máy khách có thể tạo một scriptthẻ trỏ đến api.yoursite.com/your/endpoint?name=Johnvà có valueOfCallbackHerehàm (sẽ phải được định nghĩa trong JS phía máy khách) được gọi với dữ liệu từ nguồn gốc khác này .)


và tốt hơn là không sử dụng các kỹ thuật này mà thay vào đó sử dụng JSON-JBuilder và Eager Loading? Hay tôi nhầm lẫn và chúng là hai thứ khác nhau.?

1
@ user1899082 - những kỹ thuật này thực sự là những khái niệm cấp thấp hơn những gì bạn sẽ lo lắng khi sử dụng JBuilder chẳng hạn - không có lý do gì bạn không thể sử dụng JBuilder để tuần tự hóa các đối tượng dễ dàng hơn bên trong các to_jsonphương thức của bạn - trộn và phù hợp với cả hai render :json => some_object_that_uses_JBuilder_to_render_its_jsonlà (theo như tôi có thể nói) licit.
Sean Vieira

Cảm ơn Sean, lời giải thích của bạn đã giúp tôi biết về cách kết xuất json với callback, điều này đã giải quyết được một trong những vấn đề của tôi.
Abhi,

67

Bạn muốn biết chính xác những gì? ActiveRecord có các phương thức tuần tự hóa các bản ghi thành JSON. Ví dụ: mở bảng điều khiển rails của bạn và nhập ModelName.all.to_jsonvà bạn sẽ thấy đầu ra JSON. render :jsonvề cơ bản gọi to_jsonvà trả về kết quả cho trình duyệt với các tiêu đề chính xác. Điều này hữu ích cho các cuộc gọi AJAX trong JavaScript mà bạn muốn trả về các đối tượng JavaScript để sử dụng. Ngoài ra, bạn có thể sử dụng callbacktùy chọn để chỉ định tên của lệnh gọi lại mà bạn muốn gọi qua JSONP.

Ví dụ, giả sử chúng ta có một Usermô hình giống như sau:{name: 'Max', email:' m@m.com'}

Chúng tôi cũng có một bộ điều khiển trông giống như sau:

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        render json: @user
    end
end

Bây giờ, nếu chúng ta thực hiện một cuộc gọi AJAX bằng jQuery như sau:

$.ajax({
    type: "GET",
    url: "/users/5",
    dataType: "json",
    success: function(data){
        alert(data.name) // Will alert Max
    }        
});

Như bạn có thể thấy, chúng tôi đã quản lý để lấy Người dùng có id 5 từ ứng dụng rails của chúng tôi và sử dụng nó trong mã JavaScript của chúng tôi vì nó được trả về dưới dạng đối tượng JSON. Tùy chọn gọi lại chỉ gọi một hàm JavaScript của tên được truyền với đối tượng JSON làm đối số đầu tiên và duy nhất.

Để đưa ra ví dụ về callbacktùy chọn, hãy xem phần sau:

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        render json: @user, callback: "testFunction"
    end
end

Bây giờ chúng ta có thể đóng một yêu cầu JSONP như sau:

function testFunction(data) {
    alert(data.name); // Will alert Max
};

var script = document.createElement("script");
script.src = "/users/5";

document.getElementsByTagName("head")[0].appendChild(script);

Động cơ để sử dụng lệnh gọi lại như vậy thường là để phá vỡ các biện pháp bảo vệ của trình duyệt hạn chế chia sẻ tài nguyên nguồn gốc chéo (CORS). Tuy nhiên, JSONP không còn được sử dụng nhiều nữa vì các kỹ thuật khác tồn tại để vượt qua CORS an toàn hơn và dễ dàng hơn.


Bạn có thể mở rộng ví dụ của mình một chút không? Thêm một callback:tùy chọn trong renderphương thức, sau đó hiển thị nó bên trong Ajaxcuộc gọi.
Arup Rakshit

15

Ví dụ về

render :json => @projects, :include => :tasks

Bạn đang nói rằng bạn muốn hiển thị @projectsdưới dạng JSON và bao gồm liên kết taskstrên mô hình Dự án trong dữ liệu được xuất.

Ví dụ về

render :json => @projects, :callback => 'updateRecordDisplay'

Bạn đang nói rằng bạn muốn hiển thị @projectsdưới dạng JSON và bọc dữ liệu đó trong một lệnh gọi javascript sẽ hiển thị giống như sau:

updateRecordDisplay({'projects' => []})

Điều này cho phép dữ liệu được gửi đến cửa sổ mẹ và bỏ qua các vấn đề giả mạo giữa các trang web.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.