it-swarm-tr.com

JSON çıktımı Ruby on Rails'de nasıl "güzel" biçimlendirebilirim?

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

Şu anda, to_json'u çağırıyorum ve JSON'um tek bir satırda. Bazen bu JSON çıkış akışında bir sorun olup olmadığını görmek zor olabilir.

JSON'umu Rails'te "güzel" veya güzel bir şekilde biçimlendirmek için bir yapılandırma yöntemi veya yöntemi var mı?

578
JP Richardson

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

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

Hangisi seni alır:

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

Rack Middleware ve Rails 3 sayesinde, uygulamanızın denetleyicisini değiştirmeden her istek için güzel JSON çıktısı alabilirsiniz. Bu tür bir yazılım parçacığını yazdım ve tarayıcıda ve curl çıktısında güzelce JSON yazdırdım.

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, Rails projenizin app/middleware/pretty_json_response.rb bölümüne yerleştirilmelidir. Ve son adım, ara katman yazılımını config/environments/development.rb dosyasına kaydetmektir:

config.middleware.use PrettyJsonResponse

production.rb 'da kullanmanızı önermiyorum. JSON yeniden inceleme, üretim uygulamanızın yanıt süresini ve verimini düşürebilir. Sonunda, 'X-Pretty-Json: true' başlığı gibi ekstra mantık, talep üzerine manuel kıvrılma talepleri için formatlamayı tetiklemek için tanıtılabilir.

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

70
gertas

HTML'deki <pre> etiketi, JSON.pretty_generate ile birlikte kullanılır ve JSON'u görünümünüze göre güzelleştirir. Ünlü patronum bana bunu gösterdiğinde çok mutlu oldum:

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

Eğer istersen:

  1. Uygulamanızın giden tüm JSON yanıtlarını otomatik olarak güzelleştirin.
  2. # # To_json/# as_json nesnesini kirletmekten kaçının
  3. Middleware (YUCK!) Kullanarak JSON'u ayrıştırmak/yeniden oluşturmaktan kaçının
  4. Rails WAY yap!

Ardından ... ActionController :: RONER for JSON! 'I değiştirin! Aşağıdaki kodu ApplicationController'ınıza ekleyin:

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
20
Ed Lebert

Çıkış awesome_print . JSON dizesini bir Ruby Hash olarak ayrıştırın, ardından şöyle awesome_print ile gösterin:

require "awesome_print"
require "json"

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

ap(JSON.parse(json))

Yukarıdakilerle 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 de katacaktır :)

11
Synthead

<pre> html kodunu ve pretty_generate kodunu kullanmak iyi bir şey:

<%
  require 'json'

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

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

ActiveRecord nesnesini JSON'a atma (Rails konsolunda):

pp User.first.as_json

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

Ruby'nin JSON kütüphanesinde yerleşik olan pretty_generate seçeneğinin yeterince "güzel" olmadığını fark ederseniz, biçimlendirmeniz için kendi NeatJSONNAME _ mücevherleri öneririm .

Kullanmak için gem install neatjson ve ardından JSON.neat_generate yerine JSON.pretty_generate kullanın.

Ruby'nin ppgibi, nesneler ve dizileri yerleştirildiklerinde bir satırda tutarlar, ancak gerektiği kadar çoklu sarılırlar. Ö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, kolonlardan önce/sonra kaç boşluk? Virgüllerden önce/sonra? Dizilerin ve nesnelerin parantezlerinin içinde mi? Nesnenizin anahtarlarını sıralamak ister misiniz? Kolonların sıralanmasını istiyor musun?

10
Phrogz

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

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

Bu kod app/middleware/pretty_json_response.rb 'de girilir:

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/environments/test.rb ve config/environments/development.rb dosyasına ekleyin:

config.middleware.use "PrettyJsonResponse"

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

Raylarla Test Edildi 4.1.6.

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

Gem CodeRay kullandım ve oldukça iyi çalışıyor. Format, renkleri içerir ve birçok farklı formatı tanır.

Rails API'lerinde hata ayıklamak için kullanılabilecek bir gem üzerinde kullandım ve oldukça iyi çalışıyor.

Bu arada, gem 'api_Explorer' olarak adlandırılır ( http://www.github.com/toptierlabs/api_Explorer )

2
Tony

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

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

İşte kendi araştırmam sırasında diğer yayınlardan elde ettiğim çözümüm.

Bu, pp ve jj çıkışı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
2

Başlıkları, durumu ve JSON çıkışını küme olarak yararlı bulduğumda aşağıdakileri kullanıyorum. Çağrı rutini şu adresteki bir demiryolunun sunumundan gelen öneri üzerine çıkarıldı: http://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
1
TheDadman

RABL kullanıyorsanız, JSON.pretty_generate özelliğini kullanmak için burada tanımlandığı şekilde 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 kullanarak bir sorun JSON şema doğrulayıcıları artık tarih dizeleri ile mutlu olmayacak olmasıdır. Config/initializers/rabl_config.rb dosyanızdakileri aşağıdakilerle 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
1
Jim Flood

# example of use:
a_hash = {user_info: {type: "query_service", e_mail: "[email protected]", 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
Sergio Belevskij

Oldukça baskı çeşidi:

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
SergA