Ruby on Rails'te JSON çıktısını “güzel” olarak biçimlendirme


626

Ruby on Rails'deki JSON çıktımın "güzel" veya güzel biçimlendirilmiş olmasını istiyorum.

Şu anda aradım to_jsonve JSON'umun hepsi tek bir hatta. Bazen bu JSON çıktı akışında bir sorun olup olmadığını görmek zor olabilir.

JSON'umu "güzel" veya Rails'te güzel bir şekilde biçimlendirmek için yapılandırmanın bir yolu var mı?


2
Nereye baktığınızdan emin değilsiniz, ancak webkit konsolunda, günlüğe kaydedilen veya istenen herhangi bir JSON'dan güzel bir ağaç oluşturur.
Ryan Florence

8
Bunu yaparken hatırlanması gereken bir şey, JSON içeriğinizin ek boşluk nedeniyle balonlanacağıdır. Bir geliştirme ortamında JSON'un okunması kolay olur, ancak bir üretim ortamında içeriğinizin kullanıcının tarayıcısında hız ve yanıt verebilirlik için alabileceğiniz kadar yalın olmasını istersiniz.
Tin Man

2
y my_jsonbazı hızlı düzeltme istiyorsanız kullanımı güzel şeyler biçimlendirecektir.
randomor

5
@randomorundefined method 'y' for main:Object
nurettin

yraylar konsolunda mevcuttur.
Sophia Feng

Yanıtlar:


999

pretty_generate()JSON'un sonraki sürümlerinde yerleşik olan işlevi kullanın . Örneğin:

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

Hangi sizi alır:

{
  "array": [
    1,
    2,
    3,
    {
      "sample": "hash"
    }
  ],
  "foo": "bar"
}

32
Şık! Bunu ~ / .irbrc'ye koydum: def json_pp (json) JSON.pretty_generate (JSON.parse (json)) sonuna koyar
TheDeadSerious

10
Bunu Rails'te kullanışlı hale getirmek için,format.json { render :json => @whatever }
iconoclast

9
Kesinlikle güzel baskı sadece sunucu tarafı hata ayıklama için kullanılmalıdır? Yukarıdaki kodu bir denetleyiciye yapıştırırsanız, tüm yanıtlarda tonlarca işe yaramaz boşluk olacaktır, bu da tuz tarafındaki değerli araçlar (örneğin Firebug) zaten güzel yazdırılan JSON'u işlediğinden istemci tarafı hata ayıklaması için bile gerekli değildir.
lambshaanxy

8
@jpatokal: başka daha iyi seçenekler olduğunu düşünebilirsiniz, ancak soru bunun Rails'te nasıl çalışılacağıydı. "Bunu Raylarda yapmak istemezsiniz" demek bir cevap değildir. Açıkçası bir çok insan bunu Rails'de yapmak istiyor.
iconoclast

39
Orijinal afişi hakkında hiçbir şey söylemedi nereye yerde çalışacak Ruby bir çizgi ile cevap yüzden, bir Raylar uygulamasında o bu kullanmak istiyor. Rails içinde JSON yanıtını oluşturmak için Kullanmak için denetleyici , zaten kendi soruyu yanıtladı: format.json { render :json => JSON.pretty_generate(my_json) }.
lambshaanxy

78

Rack Middleware ve Rails 3 sayesinde, uygulamanızın herhangi bir denetleyicisini değiştirmeden her istek için güzel JSON çıktısı alabilirsiniz. Böyle bir ara katman pasajı yazdım ve tarayıcı ve curlçıktı güzel JSON yazdırılır olsun .

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

Yukarıdaki kod app/middleware/pretty_json_response.rbRails projenize yerleştirilmelidir . Ve son adım, ara katman yazılımını kaydetmek config/environments/development.rb:

config.middleware.use PrettyJsonResponse

İçinde kullanmanızı tavsiye etmiyorumproduction.rb . JSON yeniden analizi, üretim uygulamanızın yanıt süresini ve verimini düşürebilir. Sonunda 'X-Pretty-Json: true' başlığı gibi ekstra mantık, isteğe bağlı manuel kıvırma istekleri için biçimlendirmeyi tetiklemek üzere kullanılabilir.

(Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux ile test edilmiştir)


2
ActiveSupport'un to_json'u yeniden tanımlamasını nasıl başaracaksınız? Bu, ActiveSupport varken güzel baskı almamı engelliyor.
Cephane Goettsch

1
Gerçekten umurumda değil, to_json, as_json, çoğunlukla kullandığım jbuilder - ne olursa olsun, ara katman yazılımı herhangi bir JSON çıktısını dönüştürür. Mümkün olduğunca ders açmaktan kaçınmaya çalışıyorum.
gertas

1
obj = JSON.parse(response.body.first)Çalışması için ayrıştırma hattını değiştirmek zorunda kaldım .
Kimmo Lehto

5
Rails 4'te de harika çalışıyor ... teşekkürler! Bunu daha çok kütüphaneye özgü yöntemlere tercih ediyorum (kabul edilen cevapta olduğu gibi). Bunu sadece geliştirici modunda kullanmanız gerektiğinden, performans isabeti önemli değildir.
elsurudo

3
Rails 5 değiştirmek Rack::Utils.bytesize(pretty_str).to_szorunda kaldı pretty_str.bytesize.to_sve harika çalışıyor!
panteo

77

<pre>İle kullanılan HTML etiketi, JSON.pretty_generatesenin görünümünde oldukça JSON hale getirecek. Ünlü patronum bana bunu gösterdiğinde çok mutlu oldum:

<% if @data.present? %>
   <pre><%= JSON.pretty_generate(@data) %></pre>
<% end %>

5
Çok temiz ve özlü!
Sean Szurko

23

Eğer istersen:

  1. Uygulamanızdan giden tüm JSON yanıtlarını otomatik olarak önizleyin.
  2. # To_json / # as_json Nesnesini kirletmekten kaçının
  3. Ara katman yazılımı (YUCK!) Kullanarak JSON'u ayrıştırmak / yeniden oluşturmaktan kaçının
  4. DEMİRYOLU YAPIN!

Sonra ... ActionController :: JSON için işleyiciyi değiştirin! Aşağıdaki kodu ApplicationController'ınıza eklemeniz yeterlidir:

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

Bu harika, ancak aslında tarihlerin / saatlerin farklı şekilde oluşturulmasına neden oluyor: gist.github.com/nornagon/9c24b68bd6d3e871add3
nornagon

Bununla ilgili çeşitli sorunlar: (1) JSON.pretty_generate json.respond_to?(:to_h)veya gerektirir :to_hash. (2) pretty_generate to_json'un yapmadığı şeyleri boğabilir.
Christopher Oezbek

@nornagon Bu değişikliği uygulamadım ve .to_json ile pretty_generate arasında gördüğünüz farkı alıyorum. Sadece bir ray konsolunda görüyorum, düz irb değil. Bunun genel raylar olayı olabileceğini düşünüyorum, bu yama ile ilgisi yok. Ayrıca, dizeyi her iki biçim için de zamana dönüştürdüğünüzde Time.parse aynı sonucu döndürür. Zaman damgaları için günlükleri ararken sadece küçük bir rahatsızlık olurdu, ancak yine de birkaç \ s + eklemek gerçekten çok önemli değil.
con--

@nornagon, gördüğünüz sorun ActiveSupport'un Ammo
Goettsch'un

17

Harika Yazdır'a göz atın . JSON dizesini bir Ruby Hash olarak ayrıştırın, ardından şu şekilde görüntüleyin ap:

require "awesome_print"
require "json"

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

ap(JSON.parse(json))

Yukarıdakilerle şunları göreceksiniz:

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

Awesome Print ayrıca Stack Overflow'un size göstermeyeceği bir renk ekler.


2
Sana katılıyorum! awesome_print basit harika!
Aashish

2
Awesome_print'i projelerimiz için de kullanıyoruz ve adı -> awesome
Simon Franzen gibi çalışıyor

13

ActiveRecord nesnesini JSON'a boşaltma (Rails konsolunda):

pp User.first.as_json

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

3
ppyazdırmak yerine standart çıktıya bir dize almak için kullanın User.first.as_json.pretty_inspect. Benim için iyi çalışıyor.
Johnny Wong

12

<pre>HTML kodu kullanmak ve pretty_generateiyi hile:

<%
  require 'json'

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

<pre>
  <%=  JSON.pretty_generate(hash) %>
</pre>

12

Eğer fark ederseniz pretty_generateRuby'nin JSON kitaplığından yerleşik seçeneği "hoş" yeterli değildir, benim kendi tavsiye NeatJSON senin biçimlendirme için mücevher.

Kullanmak için:

gem install neatjson

ve sonra kullan

JSON.neat_generate

onun yerine

JSON.pretty_generate

Ruby ppgibi, nesneleri ve dizileri sığdırdıklarında tek bir satırda tutacak, ancak gerektiğinde çoklu olarak saracaktır. Örneğin:

{
  "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?"}
  ]
}

Çıktınızı daha da özelleştirmek için çeşitli biçimlendirme seçeneklerini de destekler . Örneğin, iki nokta üst üste işaretinden önce / sonra kaç boşluk var? Virgülden önce / sonra mı? Dizilerin ve nesnelerin parantezinin içinde mi? Nesnenizin anahtarlarını sıralamak ister misiniz? İki nokta üst üste dizilerinin dizilmesini ister misiniz?


2
Bu taş kayalar - iki nokta üst üste hizalama özellikle tatlı!
webdevguy

8

İşte @gertas'ın bu mükemmel cevabından değiştirilmiş bir ara katman çözümü . Bu çözüm Rails'e özgü değildir - herhangi bir Rack uygulamasıyla çalışmalıdır.

Burada kullanılan ara katman tekniği (#each) ASCIIcasts 151: Eifion Bedford tarafından Rack Middleware'de açıklanmıştır .

Bu kod app / middleware / pretty_json_response.rb dosyasına girer :

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

Açmak için bunu config / environment / test.rb ve config / environment / development.rb dosyasına ekleyin:

config.middleware.use "PrettyJsonResponse"

@Gertas bu çözümün versiyonunda uyardığı gibi, bunu üretimde kullanmaktan kaçının. Biraz yavaş.

Raylarla Test Edildi 4.1.6.



4

İşte kendi aramam sırasında diğer gönderilerden aldığım çözümüm.

Bu, pp ve jj çıktısını gerektiği gibi bir dosyaya göndermenizi sağlar.

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

3

Gem CodeRay kullandık ve oldukça iyi çalışıyor. Biçim renkleri içerir ve birçok farklı biçimi tanır.

Ben raylar API hata ayıklama için kullanılabilir bir mücevher kullandık ve oldukça iyi çalışıyor.

Bu arada, mücevher 'api_explorer' olarak adlandırıldı ( http://www.github.com/toptierlabs/api_explorer )


3

JSON yanıtı göndermek için bunu bir Rails denetleyici eyleminde hızlıca uygulamak istiyorsanız:

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

2

RABL kullanıyorsanız, JSON.pretty_generate kullanmak için burada açıklandığı gibi yapılandırabilirsiniz :

class PrettyJson
  def self.dump(object)
    JSON.pretty_generate(object, {:indent => "  "})
  end
end

Rabl.configure do |config|
  ...
  config.json_engine = PrettyJson if Rails.env.development?
  ...
end

JSON.pretty_generate kullanmayla ilgili bir sorun, JSON şema doğrulayıcılarının artık datetime dizelerinizden memnun olmayacağıdır. Config / initializers / rabl_config.rb dosyasındaki bunları aşağıdaki yollarla düzeltebilirsiniz:

ActiveSupport::TimeWithZone.class_eval do
  alias_method :orig_to_s, :to_s
  def to_s(format = :default)
    format == :default ? iso8601 : orig_to_s(format)
  end
end

2

# example of use:
a_hash = {user_info: {type: "query_service", e_mail: "my@email.com", phone: "+79876543322"}, cars_makers: ["bmw", "mitsubishi"], car_models: [bmw: {model: "1er", year_mfc: 2006}, mitsubishi: {model: "pajero", year_mfc: 1997}]}
pretty_html = a_hash.pretty_html

# include this module to your libs:
module MyPrettyPrint
    def pretty_html indent = 0
        result = ""
        if self.class == Hash
            self.each do |key, value|
                result += "#{key}

: #{[Array, Hash].include?(value.class) ? value.pretty_html(indent+1) : value}

" end elsif self.class == Array result = "[#{self.join(', ')}]" end "#{result}" end end class Hash include MyPrettyPrint end class Array include MyPrettyPrint end

1

Başlıkları, durumu ve JSON çıktısını küme olarak yararlı bulduğum için aşağıdakileri kullanıyorum. Çağrı rutini, http://railscasts.com/episodes/151-rack-middleware?autoplay=true adresindeki bir raylı yayın sunumunun önerisi üzerine dağıtılmıştır.

  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

1

Güzel baskı varyantı:

my_object = { :array => [1, 2, 3, { :sample => "hash"}, 44455, 677778, 9900 ], :foo => "bar", rrr: {"pid": 63, "state": false}}
puts my_object.as_json.pretty_inspect.gsub('=>', ': ')

Sonuç:

{"array": [1, 2, 3, {"sample": "hash"}, 44455, 677778, 9900],
 "foo": "bar",
 "rrr": {"pid": 63, "state": false}}

0

En basit örnek, düşünebilirim:

my_json = '{ "name":"John", "age":30, "car":null }'
puts JSON.pretty_generate(JSON.parse(my_json))

Raylar konsolu örneği:

core dev 1555:0> my_json = '{ "name":"John", "age":30, "car":null }'
=> "{ \"name\":\"John\", \"age\":30, \"car\":null }"
core dev 1556:0> puts JSON.pretty_generate(JSON.parse(my_json))
{
  "name": "John",
  "age": 30,
  "car": null
}
=> nil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.