我如何“漂亮”在Ruby on Rails中格式化我的JSON輸出?




ruby-on-rails pretty-print (11)

HTML中的<pre>標記與JSON.pretty_generate一起JSON.pretty_generate ,將在您的視圖中呈現JSON。 當我的傑出老闆向我展示這件事時,我非常高興:

<% if [email protected]? %>
   <pre><%= JSON.pretty_generate(@data) %></pre>
<% end %>

我希望我的Ruby on Rails中的JSON輸出為“漂亮”或格式良好。

現在,我打電話給to_json ,我的JSON全部在一行上。 有時候,如果JSON輸出流中存在問題,可能很難查看。

有沒有辦法配置或使我的JSON“漂亮”或良好格式在Rails中的方法?


使用<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>

如果你想:

  1. 自動從您的應用程序中優化所有傳出的JSON響應。
  2. 避免污染Object#to_json /#as_json
  3. 避免使用中間件解析/重新渲染JSON(YUCK!)
  4. 做它的方式!

然後...替換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

如果你(比如我)發現Ruby的JSON庫中內置的pretty_generate選項不夠“美觀”,我推薦自己的NeatJSON gem來進行格式化。

要使用它, gem install neatjson使用gem install neatjson ,然後使用JSON.neat_generate而不是JSON.pretty_generate

像Ruby的pp一樣,它會在對象和數組合pp將對象和數組保存在一行中,但是會根據需要將其包裝為多個。 例如:

{
  "navigation.createroute.poi":[
    {"text":"Lay in a course to the Hilton","params":{"poi":"Hilton"}},
    {"text":"Take me to the airport","params":{"poi":"airport"}},
    {"text":"Let's go to IHOP","params":{"poi":"IHOP"}},
    {"text":"Show me how to get to The Med","params":{"poi":"The Med"}},
    {"text":"Create a route to Arby's","params":{"poi":"Arby's"}},
    {
      "text":"Go to the Hilton by the Airport",
      "params":{"poi":"Hilton","location":"Airport"}
    },
    {
      "text":"Take me to the Fry's in Fresno",
      "params":{"poi":"Fry's","location":"Fresno"}
    }
  ],
  "navigation.eta":[
    {"text":"When will we get there?"},
    {"text":"When will I arrive?"},
    {"text":"What time will I get to the destination?"},
    {"text":"What time will I reach the destination?"},
    {"text":"What time will it be when I arrive?"}
  ]
}

它還支持多種格式選項以進一步自定義您的輸出。 例如,冒號前/後有多少個空格? 逗號之前/之後? 在數組和對象的括號內? 你想排序你的對象的鍵? 你希望冒號排成一列嗎?


如果您希望在Rails控制器操作中快速實現此操作以發送JSON響應,請執行以下操作:

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

將ActiveRecord對象轉儲到JSON(在Rails控制台中):

pp User.first.as_json

# => {
 "id" => 1,
 "first_name" => "Polar",
 "last_name" => "Bear"
}

我使用下面的代碼,因為我發現頭文件,狀態和JSON輸出作為一個集合很有用。 呼叫例程根據以下網址上的railscast演示推薦: http://railscasts.com/episodes/151-rack-middleware?autoplay=true ://railscasts.com/episodes/151-rack-middleware?autoplay=true

  class LogJson

  def initialize(app)
    @app = app
  end

  def call(env)
    dup._call(env)
  end

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

  def each(&block)
    if @headers["Content-Type"] =~ /^application\/json/
      obj = JSON.parse(@response.body)
      pretty_str = JSON.pretty_unparse(obj)
      @headers["Content-Length"] = Rack::Utils.bytesize(pretty_str).to_s
      Rails.logger.info ("HTTP Headers:  #{ @headers } ")
      Rails.logger.info ("HTTP Status:  #{ @status } ")
      Rails.logger.info ("JSON Response:  #{ pretty_str} ")
    end

    @response.each(&block)
  end
  end

我已經使用了寶石CodeRay,它工作得很好。 格式包括顏色,它可以識別很多不同的格式。

我用它可以用於調試rails API的gem,它工作得很好。

順便說一下,該寶石被命名為'api_explorer'( http://www.github.com/toptierlabs/api_explorer


這是一個中間件解決方案, 由@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

要打開它,將其添加到config / environments / test.rb和config / environments / development.rb:

config.middleware.use "PrettyJsonResponse"

正如@gertas在他的解決方案版本中警告的,避免在生產中使用它。 這有點慢。

經過Rails 4.1.6測試。


這是我在我自己的搜索過程中從其他帖子中獲得的解決方案。

這允許您根據需要將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

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






pretty-print