首页 文章

在控制器中渲染JSON

提问于
浏览
80

我正在阅读一本书和关于控制器的章节,当它讨论渲染内容时,对于JSON,它有一个这样的例子,但没有详细说明,所以我无法弄清楚这个例子适合的大局:

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

还有JSONP使用回调函数的一些例子:

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

有人能解释一下吗?

3 回答

  • 105

    对于的例子

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

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

    对于的例子

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

    您声明要将 @projects 呈现为JSON,并将该数据包装在javascript调用中,该调用将呈现如下:

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

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

  • 12

    你究竟想知道什么? ActiveRecord具有将记录序列化为JSON的方法 . 例如,打开rails控制台并输入 ModelName.all.to_json ,您将看到JSON输出 . render :json 本质上调用 to_json 并使用正确的 Headers 将结果返回给浏览器 . 这对于要在其中返回要使用的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对象作为第一个也是唯一参数传递的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 .

  • 55

    您通常会返回JSON因为:

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

    要么

    B)您正在构建第三方将消耗的API,并且您决定使用JSON来序列化您的数据 .

    或者,您可能正在吃自己的狗食并同时做两种情况

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

    为什么:回调?

    JSONP(第二个例子)是一种绕过Same Origin Policy的方法,它是每个浏览器内置安全性的一部分 . 如果您的API位于 api.yoursite.com ,并且您将从 services.yoursite.com 起为您的应用程序提供服务,那么您的JavaScript将不会(默认情况下)能够将 XMLHttpRequest (XHR - aka ajax)请求从 services 发送到 api . 人们一直在寻找这种限制(在Cross-Origin Resource Sharing spec was finalized之前)的方式是通过从服务器发送JSON数据,就像它是JavaScript而不是JSON一样 . 因此,而不是发回:

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

    服务器将发回:

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

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

相关问题