如何在Ruby on Rails中"漂亮"格式化我的JSON输出?

JP *_*son 600 ruby json ruby-on-rails pretty-print

我希望Ruby on Rails中的JSON输出"漂亮"或格式良好.

现在,我打电话to_json,我的JSON全部在一条线上.有时,如果JSON输出流中存在问题,则很难看到.

有没有办法配置或方法使我的JSON在Rails中"漂亮"或格式良好?

jpa*_*kal 953

使用pretty_generate()内置于更高版本的JSON中的函数.例如:

require 'json'
my_object = { :array => [1, 2, 3, { :sample => "hash"} ], :foo => "bar" }
puts JSON.pretty_generate(my_object)
Run Code Online (Sandbox Code Playgroud)

哪个让你:

{
  "array": [
    1,
    2,
    3,
    {
      "sample": "hash"
    }
  ],
  "foo": "bar"
}
Run Code Online (Sandbox Code Playgroud)

  • 最初的海报在Rails应用程序中没有提到_where_他想要使用它,所以我回答了一系列随处可用的Ruby.要使用它在Rails*controller*中生成JSON响应,您已经回答了自己的问题:`format.json {render:json => JSON.pretty_generate(my_json)}`. (38认同)
  • 漂亮!我把它放到我的〜/ .irbrc中:def json_pp(json)把JSON.pretty_generate(JSON.parse(json))结束 (30认同)
  • 为了使它在Rails中有用,似乎你应该给出一个答案,其中包括可以在与`format.json {render:json => @whatever}相同的上下文中使用的代码. (9认同)
  • 当然,prettyprinting只应用于服务器端调试?如果您将上面的代码粘贴在控制器中,那么在所有响应中都会有大量无用的空白,这对于客户端调试来说甚至都不需要,因为任何值得他们使用的工具(例如Firebug)已经处理了漂亮的JSON. (9认同)
  • @jpatokal:你可能会认为还有其他更好的选择,但问题是如何让它在Rails中运行.说"你不想在Rails中这样做"是一个不答案.显然很多人都想在Rails中做到这一点. (7认同)
  • @jpatokal上面对`render`的评论对我不起作用.我不得不稍微修改一下:`render:json => JSON.pretty_generate(JSON.parse(my_json))` (2认同)
  • 控制台 `jj` 中还有一个方便的方法,它可以将 json 对象漂亮地打印到 STDOUT (2认同)

ger*_*tas 73

感谢Rack Middleware和Rails 3,您可以为每个请求输出漂亮的JSON,而无需更改应用程序的任何控制器.我已经写了这样的中间件片段,我在浏览器和curl输出中得到了很好的印刷JSON .

class PrettyJsonResponse
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)
    if headers["Content-Type"] =~ /^application\/json/
      obj = JSON.parse(response.body)
      pretty_str = JSON.pretty_unparse(obj)
      response = [pretty_str]
      headers["Content-Length"] = pretty_str.bytesize.to_s
    end
    [status, headers, response]
  end
end
Run Code Online (Sandbox Code Playgroud)

上面的代码应该放在app/middleware/pretty_json_response.rb你的Rails项目中.最后一步是将中间件注册到config/environments/development.rb:

config.middleware.use PrettyJsonResponse
Run Code Online (Sandbox Code Playgroud)

我不建议使用它production.rb.JSON重新分析可能会降低生产应用程序的响应时间和吞吐量.最终可能引入额外的逻辑,例如'X-Pretty-Json:true'标题,以按需触发手动卷曲请求的格式化.

(使用Rails 3.2.8-5.0.0,Ruby 1.9.3-2.2.0,Linux测试)

  • 在Rails 4中也很棒......谢谢!我更喜欢使用更多特定于库的方法(如在接受的答案中).因为你只应该在开发模式下使用它,性能命中并不是什么大问题. (5认同)
  • 在Rails 5中,我不得不将`Rack :: Utils.bytesize(pretty_str).to_s`更改为`pretty_str.bytesize.to_s`并且效果很好! (3认同)
  • 您如何绕过to_json的ActiveSupport的[redefinition](https://github.com/rails/rails/blob/3-0-stable/activesupport/lib/active_support/core_ext/object/to_json.rb)?存在ActiveSupport时,这使我无法进行漂亮的打印。 (2认同)

Rog*_*rza 69

<pre>与HTML一起使用的标记JSON.pretty_generate将在您的视图中呈现JSON.当我的杰出老板告诉我这件事时,我很高兴:

<% if @data.present? %>
   <pre><%= JSON.pretty_generate(@data) %></pre>
<% end %>
Run Code Online (Sandbox Code Playgroud)

  • 如此简洁明了! (4认同)

小智 22

如果你想:

  1. 自动从您的应用程序中清除所有传出的JSON响应.
  2. 避免污染Object#to_json/#as_json
  3. 避免使用中间件解析/重新呈现JSON(YUCK!)
  4. 以RAILS方式做吧!

然后......替换JSON的ActionController :: Renderer!只需将以下代码添加到ApplicationController:

ActionController::Renderers.add :json do |json, options|
  unless json.kind_of?(String)
    json = json.as_json(options) if json.respond_to?(:as_json)
    json = JSON.pretty_generate(json, options)
  end

  if options[:callback].present?
    self.content_type ||= Mime::JS
    "#{options[:callback]}(#{json})"
  else
    self.content_type ||= Mime::JSON
    json
  end
end
Run Code Online (Sandbox Code Playgroud)


Syn*_*ead 15

看看awesome_print.将JSON字符串解析为Ruby Hash,然后使用awesome_print显示它,如下所示:

require "awesome_print"
require "json"

json = '{"holy": ["nested", "json"], "batman!": {"a": 1, "b": 2}}'

ap(JSON.parse(json))
Run Code Online (Sandbox Code Playgroud)

有了上述内容,您将看到:

{
  "holy" => [
    [0] "nested",
    [1] "json"
  ],
  "batman!" => {
    "a" => 1,
    "b" => 2
  }
}
Run Code Online (Sandbox Code Playgroud)

awesome_print还会添加一些Stack Overflow不会显示的颜色:)

  • 同意您!awesome_print很简​​单! (2认同)
  • 我们也在我们的项目中使用awesome_print,它的工作方式就像名称-&gt; awesome (2认同)

Tho*_*emm 12

将ActiveRecord对象转储到JSON(在Rails控制台中):

pp User.first.as_json

# => {
 "id" => 1,
 "first_name" => "Polar",
 "last_name" => "Bear"
}
Run Code Online (Sandbox Code Playgroud)

  • 要从pp获取字符串而不是打印到标准输出,请使用User.first.as_json.pretty_inspect。对我来说效果很好。 (3认同)

Phr*_*ogz 12

如果你(像我一样)发现pretty_generateRuby的JSON库中内置的选项不够"漂亮",我推荐自己的ppgem用于格式化.

要使用它pretty_generate然后使用pp而不是pretty_generate.

像Ruby一样,pp它会在适合的时候将对象和数组放在一行上,但根据需要包装到多个.例如:

gem install neatjson
Run Code Online (Sandbox Code Playgroud)

它还支持各种格式化选项,以进一步自定义输出.例如,冒号之前/之后有多少个空格?逗号之前/之后?在数组和对象的括号内?你想对对象的键进行排序吗?你想要将所有冒号排成一列吗?

  • 这种宝石-结肠上的排列特别甜蜜! (2认同)
  • 我也喜欢格式化!一个非常酷的选择。 (2认同)

oj5*_*5th 12

使用<pre>HTML代码,pretty_generate是一个很好的技巧:

<%
  require 'json'

  hash = JSON[{hey: "test", num: [{one: 1, two: 2, threes: [{three: 3, tthree: 33}]}]}.to_json] 
%>

<pre>
  <%=  JSON.pretty_generate(hash) %>
</pre>
Run Code Online (Sandbox Code Playgroud)


Way*_*rad 7

这是一个由@gertas的优秀答案修改的中间件解决方案.此解决方案不是Rails特定的 - 它应该适用于任何Rack应用程序.

这里使用的中间件技术,使用#each,由Eifion Bedford的ASCIIcasts 151:Rack Middleware解释.

此代码位于app/middleware/pretty_json_response.rb中:

class PrettyJsonResponse

  def initialize(app)
    @app = app
  end

  def call(env)
    @status, @headers, @response = @app.call(env)
    [@status, @headers, self]
  end

  def each(&block)
    @response.each do |body|
      if @headers["Content-Type"] =~ /^application\/json/
        body = pretty_print(body)
      end
      block.call(body)
    end
  end

  private

  def pretty_print(json)
    obj = JSON.parse(json)  
    JSON.pretty_unparse(obj)
  end

end
Run Code Online (Sandbox Code Playgroud)

要打开它,请将其添加到config/environments/test.rb和config/environments/development.rb:

config.middleware.use "PrettyJsonResponse"
Run Code Online (Sandbox Code Playgroud)

正如@gertas在他的解决方案版本中警告的那样,避免在生产中使用它.这有点慢.

用Rails 4.1.6测试.


Tor*_*sDB 6

如果你想处理active_record对象,puts就足够了。

例如:

  • 没有puts
2.6.0 (main):0 > User.first.to_json
  User Load (0.4ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
=> "{\"id\":1,\"admin\":true,\"email\":\"admin@gmail.com\",\"password_digest\":\"$2a$10$TQy3P7NT8KrdCzliNUsZzuhmo40LGKoth2hwD3OI.kD0lYiIEwB1y\",\"created_at\":\"2021-07-20T08:34:19.350Z\",\"updated_at\":\"2021-07-20T08:34:19.350Z\",\"name\":\"Arden Stark\"}"
Run Code Online (Sandbox Code Playgroud)
  • puts
2.6.0 (main):0 > puts User.first.to_json
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
{"id":1,"admin":true,"email":"admin@gmail.com","password_digest":"$2a$10$TQy3P7NT8KrdCzliNUsZzuhmo40LGKoth2hwD3OI.kD0lYiIEwB1y","created_at":"2021-07-20T08:34:19.350Z","updated_at":"2021-07-20T08:34:19.350Z","name":"Arden Stark"}
=> nil
Run Code Online (Sandbox Code Playgroud)

如果您要处理 json 数据,JSON.pretty_generate是一个不错的选择

例子:

obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
json = JSON.pretty_generate(obj)
puts json
Run Code Online (Sandbox Code Playgroud)

输出:

{
  "foo": [
    "bar",
    "baz"
  ],
  "bat": {
    "bam": 0,
    "bad": 1
  }
}
Run Code Online (Sandbox Code Playgroud)

如果是在 ROR 项目中,我总是更喜欢使用 gempry-rails来格式化我的代码,rails console而不是awesome_print太冗长。

示例pry-rails

在此输入图像描述

它还具有语法突出显示。


小智 5

这是我在自己搜索期间从其他帖子中得出的解决方案。

这允许您根据需要将 pp 和 jj 输出发送到文件。

require "pp"
require "json"

class File
  def pp(*objs)
    objs.each {|obj|
      PP.pp(obj, self)
    }
    objs.size <= 1 ? objs.first : objs
  end
  def jj(*objs)
    objs.each {|obj|
      obj = JSON.parse(obj.to_json)
      self.puts JSON.pretty_generate(obj)
    }
    objs.size <= 1 ? objs.first : objs
  end
end

test_object = { :name => { first: "Christopher", last: "Mullins" }, :grades => [ "English" => "B+", "Algebra" => "A+" ] }

test_json_object = JSON.parse(test_object.to_json)

File.open("log/object_dump.txt", "w") do |file|
  file.pp(test_object)
end

File.open("log/json_dump.txt", "w") do |file|
  file.jj(test_json_object)
end
Run Code Online (Sandbox Code Playgroud)


Ton*_*ony 5

我使用过 gem CodeRay,效果非常好。该格式包括颜色,并且它可以识别许多不同的格式。

我已经在可用于调试 Rails API 的 gem 上使用了它,并且效果非常好。

顺便说一下,该 gem 名为“api_explorer”(http://www.github.com/toptierlabs/api_explorer


sea*_*cal 5

如果您希望在 Rails 控制器操作中快速实现它以发送 JSON 响应:

def index
  my_json = '{ "key": "value" }'
  render json: JSON.pretty_generate( JSON.parse my_json )
end
Run Code Online (Sandbox Code Playgroud)


Буя*_*рэн 5

#At Controller
def branch
    @data = Model.all
    render json: JSON.pretty_generate(@data.as_json)
end
Run Code Online (Sandbox Code Playgroud)