114

我正在阅读一本书,并且在关于控制器的章节中谈到渲染内容时,对于 JSON,它有一个这样的示例,但没有详细说明,所以我无法弄清楚这个示例适合的更大图景:

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

还有一些将 JSONP 与回调函数一起使用的示例:

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

有人可以解释这些吗?

4

3 回答 3

136

您通常会返回JSON,因为:

A) 您正在将部分/全部应用程序构建为单页应用程序 (SPA),并且您需要客户端 JavaScript 能够在不完全重新加载页面的情况下提取额外数据。

或者

B) 您正在构建一个第三方将使用的 API,并且您已决定使用 JSON 来序列化您的数据。

或者,可能,你正在吃你自己的狗粮并且两者都做

在这两种情况下render :json => some_data,都会对提供的数据进行 JSON 化。第二个示例中的:callback关键需要更多解释(见下文),但它是同一想法的另一种变体(以 JavaScript 可以轻松处理的方式返回数据。)

为什么:callback

JSONP(第二个示例)是一种绕过同源策略的方法,该策略是每个浏览器内置安全性的一部分。如果您有您的 API,api.yoursite.com并且您将通过 JavaScript 为您的应用程序提供服务,services.yoursite.com那么(默认情况下)将无法从 to 发出(XMLHttpRequestXHR - aka ajax)请求。人们一直在绕过这个限制的方式(在跨域资源共享规范最终确定之前)是通过从服务器发送 JSON 数据,就好像它是 JavaScript 而不是 JSON 一样)。因此,而不是发回:servicesapi

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

服务器反而会发回:

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

因此,客户端 JS 应用程序可以创建一个script指向的标记,api.yoursite.com/your/endpoint?name=John并使用来自其他来源的数据valueOfCallbackHere调用函数(必须在客户端 JS 中定义)。)

于 2013-02-12T02:53:48.923 回答
74

你到底想知道什么?ActiveRecord 具有将记录序列化为 JSON 的方法。例如,打开您的 rails 控制台并输入ModelName.all.to_json,您将看到 JSON 输出。render :json本质上调用to_json并使用正确的标头将结果返回给浏览器。这对于您希望返回 JavaScript 对象以供使用的 JavaScript 中的 AJAX 调用很有用。此外,您可以使用该callback选项指定要通过 JSONP 调用的回调的名称。

例如,假设我们有一个User看起来像这样的模型:{name: 'Max', email:' m@m.com'}

我们还有一个如下所示的控制器:

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

现在,如果我们像这样使用 jQuery 进行 AJAX 调用:

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

如您所见,我们设法从 Rails 应用程序中获取 ID 为 5 的用户,并在我们的 JavaScript 代码中使用它,因为它是作为 JSON 对象返回的。回调选项只是调用以 JSON 对象作为第一个也是唯一的参数传递的命名的 JavaScript 函数。

要给出该callback选项的示例,请查看以下内容:

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

现在我们可以创建一个 JSONP 请求,如下所示:

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

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

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

使用此类回调的动机通常是为了规避限制跨源资源共享 (CORS) 的浏览器保护措施。然而,JSONP 不再使用那么多了,因为存在其他更安全、更容易绕过 CORS 的技术。

于 2013-02-12T02:53:11.687 回答
18

例如

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

您声明要呈现@projects为 JSON,并将tasksProject 模型上的关联包含在导出的数据中。

例如

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

您说您想呈现@projects为 JSON,并将该数据包装在一个 javascript 调用中,该调用将呈现如下:

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

这允许将数据发送到父窗口并绕过跨站点伪造问题。

于 2013-02-12T02:52:10.003 回答