在Rails中,如何使用视图呈现JSON?

132

假设您在用户控制器中,并且希望获取显示请求的JSON响应,如果您可以在您的views/users/目录中创建一个名为show.json的文件,那将非常方便。在users#show操作完成后,它会呈现该文件。

目前,您需要执行以下操作:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json{
      render :json => @user.to_json
    }
  end
end

但如果您可以创建一个show.json文件,它会自动呈现如下:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end
这会让我省掉很多麻烦,也能避免在控制器中呈现我的JSON数据时产生的那种非常不舒服的感觉。

看着这篇帖子,现在看起来似乎并不能为我节省太多时间,但我还有更复杂的情况,相信我,这让我头痛不已。 - Matthew
1
在Rails 3中,你只需要使用一个show.json.erb文件就可以调用format.json。请查看我的回答。 - James Lim
9个回答

67
你应该能够在你的respond_to块中做类似这样的事情:
respond_to do |format|
    format.json 
    render :partial => "users/show.json"
end

这将呈现位于app/views/users/_show.json.erb的模板。


6
这很不错,但你很快会发现使用erb生成json是一种痛苦的方式。查看我的答案以了解一些替代方案。 - tybro0103
1
有没有不使用部分的方法来完成它? - Wylliam Judd

58

尝试添加一个名为users/show.json.erb的视图。当您请求JSON格式时,它会被渲染,并且由于它也将通过erb进行渲染,所以您的文件可能看起来像这样:

{
    "first_name": <%= @user.first_name.to_json %>,
    "last_name": <%= @user.last_name.to_json %>
}

(于2023年1月23日编辑,以修复值的双引号问题)


9
你可能希望使用@user.first_name.to_json代替escape_javascript。JS允许的内容和严格的JSON之间存在一些细微差别。(这些差别在浏览器实现它们自己的JSON解析器时变得越来越重要。) - James A. Rosen
1
你应该将单引号改为双引号,因为 JSON(与 JS 不同)只接受双引号字符串。 - Abe Voelker
1
这很好,但你很快会发现erb是生成json的痛苦方式。查看我的答案以了解一些替代方案。 - tybro0103
我知道这是一个老的回答,但它完全是错误的。 to_json将返回一个格式化的json字符串,因此结果json中永远不会有额外的引号(""value"")。 另外,如果用户的名字是nil,则生成的json将具有字符串“null”作为值。 此外,<%=使用HTML转义,这将破坏输入数据中的HTML字符。 - d4n3
我认为你还需要删除 <%= xyz.to_json %> 周围的引号,否则会多出一些引号。 - akostadinov

35

正如其他人提到的,您需要一个 users/show.json 视图,但是有一些选项可供模板语言考虑...

ERB

开箱即用。非常适合 HTML,但您很快会发现对于 JSON 来说很糟糕。

RABL

很好的解决方案。需要添加依赖并学习其 DSL。

JSON Builder

与 RABL 相同:很好的解决方案。需要添加依赖并学习其 DSL。

纯 Ruby

Ruby 在生成 JSON 方面非常出色,无需学习新知识,只需调用 Hash 或 AR 对象上的 to_json 即可。只需为模板注册 .rb 扩展名(在初始化器中):

ActionView::Template.register_template_handler(:rb, :source.to_proc)

然后创建视图 users/show.json.rb:

@user.to_json

了解更多关于这种方法的信息,请参见http://railscasts.com/episodes/379-template-handlers


10
请注意,在Rails 4中,默认情况下已注册.ruby模板处理程序 https://github.com/rails/rails/commit/de1060f4e02925c12004f2,因此您可以省略注册.rb并将文件命名为users/show.json.ruby。 - Tim Diggins
1
另外,为了进一步更新,json_builder已被https://github.com/rails/jbuilder取代。 - Tim Diggins

27

RABL可能是我见过的最好的解决方案,如果您正在寻找一种比ERB语法更清晰的替代方案。另外两个解决方案json_builder和argonaut似乎有些过时,并且需要一些修补才能在Rails 3.1中使用。

RABL可以通过gem包获取,或者查看GitHub存储库;还提供了良好的示例。

https://github.com/nesquena/rabl


21

为了让其他人更好地理解,我来更新一下这个答案。

在Rails 3中,你只需要在views/users/show.json.erb创建一个文件。@user对象将会像HTML一样在视图中可用。你甚至不再需要使用to_json

总之,就是:

# users contoller
def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

并且

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}

2
我在1.5年前回答过这个问题。现在每当我需要JSON时,我只是使用respond_with @user, only: [:name]。有关更多信息,请参阅此教程 - James Lim
2
仅补充一下这个答案,实际上有两个危险因素:它允许用户数据注入,因为它不转义换行符和反斜杠,而且<%=会对数据进行HTML转义,例如Sean O'Connor的名字将被破坏为Sean O'Connor。 - d4n3

10

只需添加内容为show.json.erb的文件。

<%= @user.to_json %>
有时候在控制器中需要一些额外的辅助方法,比如image_path(@user.avatar)或生成JSON中的其他属性。
<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>

8
为了避免 HTML 转义,需要使用 <%= raw(@user.to_json) %>。我通常会使用 to_json,只要它给我想要的结果,但是如果我想做其他事情,我就会使用模板,通常是 { :blah => @user.the_blah }.to_json - clacke

6

1

我是RoR的新手,这是我发现的。你可以直接呈现json格式。

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END

0

我刚开始学习RoR,如果这不是你要找的内容,请见谅。我发现这个链接可能是最新的直接方法,如https://guides.rubyonrails.org/v5.1/layouts_and_rendering.html#using-render所述。

2.2.8 渲染JSON

您不需要在要呈现的对象上调用to_json。如果使用:json选项,render将自动为您调用to_json。

在您的操作中,您只需要这样做

respond_to do |format| 
        format.html
        format.atom
        format.json { render json: @user }
end 

它会在 ./users/1/custom_action.json 中渲染您的 json 响应


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接