在控制器中呈现JSON


103

我正在阅读一本书,并在有关控制器的一章中谈到渲染的东西,对于JSON,它有一个这样的示例,但是没有详细介绍,因此我无法弄清楚该示例所适合的整体情况:

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

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

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

有人可以解释这些吗?

Answers:


127

通常,您将返回JSON的原因之一是:

A)您正在将部分/全部应用程序构建为单页应用程序(SPA),并且需要客户端JavaScript能够提取其他数据而无需完全重新加载页面。

要么

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

或者,也许,你是吃自己的狗食和做两个

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

为什么:callback

JSONP(第二个示例)是一种绕过相同起源策略的方法,该策略是每个浏览器内置安全性的一部分。如果您拥有自己的API,api.yoursite.com并且将要services.yoursite.com使用JavaScript 来提供应用程序,则(默认情况下)将无法发出来自XMLHttpRequest(XHR-aka ajax)servicesapi。人们绕过该限制的方式(在完成跨域资源共享规范之前)是通过从服务器发送JSON数据,就好像它是JavaScript而不是JSON一样。因此,与其发回:

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

服务器将发送回:

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

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


最好不完全使用这些技术,而改用JSON-JBuilder和Eager Loading吗?还是我很困惑,他们是两回事。

1
@ user1899082-这些技术实际上是比使用JBuilder时要担心的概念更底层的概念-没有理由为什么不能使用JBuilder使对象内部的序列化变得更容易to_json-混合和render :json => some_object_that_uses_JBuilder_to_render_its_json(据我所知)匹配两者是合法的。
肖恩·维埃拉

感谢Sean,您的解释帮助我了解了有关使用回调呈现json的信息,这解决了我的问题之一。
阿比

67

您到底想知道什么?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对象返回的。callback选项仅调用以JSON对象作为第一个也是唯一的参数传递的named的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的技术。


您可以扩展一下示例吗?callback:render方法中添加一个选项,然后在Ajax调用中显示它。
奥雅纳(Arup Rakshit)2015年

15

对于的实例

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

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

对于的实例

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

您声明要以@projectsJSON形式呈现,并将该数据包装在javascript调用中,呈现方式类似于:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.