Как я могу "красиво" отформатировать вывод JSON в Ruby on Rails? - PullRequest
576 голосов
/ 17 сентября 2008

Я бы хотел, чтобы мой вывод JSON в Ruby on Rails был "красивым" или красиво отформатированным.

Прямо сейчас я звоню to_json, и мой JSON находится на одной строке. Иногда бывает трудно увидеть, есть ли проблема в потоке вывода JSON.

Есть ли способ настроить или метод сделать мой JSON "красивым" или красиво отформатированным в Rails?

Ответы [ 17 ]

913 голосов
/ 01 декабря 2009

Используйте функцию pretty_generate(), встроенную в более поздние версии JSON. Например:

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

Что тебя достает:

{
  "array": [
    1,
    2,
    3,
    {
      "sample": "hash"
    }
  ],
  "foo": "bar"
}
69 голосов
/ 23 октября 2012

Благодаря Rack Middleware и Rails 3 вы можете выводить симпатичные JSON для каждого запроса без изменения какого-либо контроллера вашего приложения. Я написал такой фрагмент промежуточного программного обеспечения, и я получил хорошо напечатанный JSON в браузере и вывод curl.

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

Приведенный выше код должен быть помещен в app/middleware/pretty_json_response.rb вашего проекта Rails. И последний шаг - зарегистрировать промежуточное ПО в config/environments/development.rb:

config.middleware.use PrettyJsonResponse

Я не рекомендую использовать его в production.rb. Повторная обработка JSON может ухудшить время отклика и производительность вашего производственного приложения. Со временем может быть введена дополнительная логика, такая как заголовок «X-Pretty-Json: true», чтобы инициировать форматирование для запросов скручивания вручную по требованию.

(протестировано с Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux)

65 голосов
/ 03 июля 2013

Тег <pre> в HTML, используемый с JSON.pretty_generate, сделает JSON привлекательным на ваш взгляд. Я был так счастлив, когда мой прославленный босс показал мне это:

<code><% if @data.present? %>
   <pre><%= JSON.pretty_generate(@data) %>
<% end%>
20 голосов
/ 11 апреля 2014

Если вы хотите:

  1. Автоматическая предварительная обработка всех исходящих ответов JSON из вашего приложения.
  2. Избегать загрязнения объекта # to_json / # as_json
  3. Избегайте анализа / повторного рендеринга JSON с использованием промежуточного программного обеспечения (YUCK!)
  4. Сделай это ЖЕЛЕЗНЫМ ПУТЬ!

Тогда ... замените ActionController :: Renderer на JSON! Просто добавьте следующий код в ваш 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
11 голосов
/ 29 июня 2016

Проверить 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))

С учетом вышеизложенного вы увидите:

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

awesome_print также добавит цвет, который не будет отображаться при переполнении стека:)

10 голосов
/ 04 апреля 2014

Вывод объекта ActiveRecord в JSON (в консоли Rails):

pp User.first.as_json

# => {
 "id" => 1,
 "first_name" => "Polar",
 "last_name" => "Bear"
}
10 голосов
/ 16 апреля 2015

Если вы (как и я) обнаружите, что опция pretty_generate, встроенная в библиотеку JSON в Ruby, недостаточно «хороша», я рекомендую для своего форматирования мой собственный NeatJSON гем.

Чтобы использовать его gem install neatjson, а затем использовать JSON.neat_generate вместо JSON.pretty_generate.

Как и Ruby's 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?"}
  ]
}

Он также поддерживает различные параметры форматирования для дальнейшей настройки вывода. Например, сколько пробелов до / после двоеточия? До / после запятых? Внутри скобок массивов и объектов? Вы хотите отсортировать ключи вашего объекта? Вы хотите, чтобы все колоны были выстроены в очередь?

10 голосов
/ 03 августа 2016

Использование <pre> HTML-кода и pretty_generate хороший прием:

<code><%
  require 'json'

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

<pre>
  <%=  JSON.pretty_generate(hash) %>
6 голосов
/ 21 октября 2014

Вот промежуточное решение, измененное с на этот отличный ответ @ gertas . Это решение не является специфичным для Rails - оно должно работать с любым приложением Rack.

Используемая здесь методика промежуточного программного обеспечения с использованием #each объясняется в ASCIIcasts 151: Промежуточное программное обеспечение стойки Эфионом Бедфордом.

Этот код входит в 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 / environment / test.rb и config / environment / development.rb:

config.middleware.use "PrettyJsonResponse"

Как @gertas предупреждает в своей версии этого решения, избегайте его использования в работе. Это немного медленно.

Протестировано с Rails 4.1.6.

5 голосов
#At Controller
def branch
    @data = Model.all
    render json: JSON.pretty_generate(@data.as_json)
end
...