webentwicklung-frage-antwort-db.com.de

Wie kann ich meine JSON-Ausgabe in Ruby on Rails "hübsch" formatieren?

Ich möchte, dass meine JSON-Ausgabe in Ruby auf Rails "hübsch" oder schön formatiert ist.

Im Moment rufe ich to_json auf und mein JSON steht in einer Zeile. Manchmal kann es schwierig sein, festzustellen, ob im JSON-Ausgabestream ein Problem vorliegt.

Gibt es eine Möglichkeit zum Konfigurieren oder eine Methode, um meinen JSON in Rails "hübsch" oder schön formatiert zu machen?

583
JP Richardson

Verwenden Sie die Funktion pretty_generate(), die in späteren Versionen von JSON integriert ist. Zum Beispiel:

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

Was bringt dir:

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

Dank Rack Middleware und Rails 3 können Sie für jede Anforderung ein hübsches JSON ausgeben, ohne den Controller Ihrer App zu ändern. Ich habe ein solches Middleware-Snippet geschrieben und bekomme JSON in Browser und curl Ausgabe schön gedruckt.

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

Der obige Code sollte in app/middleware/pretty_json_response.rb Ihres Rails Projekts eingefügt werden. Und der letzte Schritt ist, die Middleware in config/environments/development.rb zu registrieren:

config.middleware.use PrettyJsonResponse

Ich empfehle nicht, es in production.rb zu verwenden. Das erneute Analysieren von JSON kann die Antwortzeit und den Durchsatz Ihrer Produktions-App beeinträchtigen. Eventuell kann eine zusätzliche Logik wie der Header 'X-Pretty-Json: true' eingeführt werden, um bei Bedarf die Formatierung für manuelle Curl-Anforderungen auszulösen.

(Getestet mit Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux)

71
gertas

Das <pre> -Tag in HTML, das mit JSON.pretty_generate verwendet wird, macht den JSON in Ihrer Ansicht hübsch. Ich war so glücklich, als mir mein berühmter Chef Folgendes zeigte:

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

Wenn du möchtest:

  1. Verschönern Sie alle ausgehenden JSON-Antworten von Ihrer App automatisch.
  2. Vermeiden Sie es, das Objekt # to_json/# as_json zu verschmutzen
  3. Vermeiden Sie es, JSON mit Middleware zu analysieren/erneut zu rendern (YUCK!)
  4. Mach es auf die Rails Weise!

Dann ... ersetzen Sie den ActionController :: Renderer für JSON! Fügen Sie Ihrem ApplicationController einfach den folgenden Code hinzu:

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

Check out awesome_print . Analysieren Sie den JSON-String in einen Ruby -Hash und zeigen Sie ihn dann mit awesome_print wie folgt an:

require "awesome_print"
require "json"

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

ap(JSON.parse(json))

Mit dem oben genannten sehen Sie:

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

awesome_print fügt auch eine Farbe hinzu, die Stack Overflow nicht anzeigt :)

12
Synthead

Die Verwendung von <pre> HTML-Code und pretty_generate ist ein guter Trick:

<%
  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

Speichern eines ActiveRecord-Objekts in JSON (in der Rails -Konsole):

pp User.first.as_json

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

Wenn Sie (wie ich) feststellen, dass die in Rubys JSON-Bibliothek integrierte Option pretty_generate nicht "hübsch" genug ist, empfehle ich mein eigenes NeatJSON gem für Ihre Formatierung.

Um es zu benutzen, gem install neatjson und dann JSON.neat_generate anstelle von JSON.pretty_generate.

Wie bei Rubys pp bleiben Objekte und Arrays in einer Zeile, wenn sie passen, werden jedoch nach Bedarf in mehrere Zeilen umbrochen. Zum Beispiel:

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

Es werden auch verschiedene Formatierungsoptionen unterstützt, um die Ausgabe weiter anzupassen. Zum Beispiel, wie viele Leerzeichen vor/nach Doppelpunkten? Vor/nach Komma? In den Klammern von Arrays und Objekten? Möchten Sie die Schlüssel Ihres Objekts sortieren? Möchten Sie, dass die Doppelpunkte in einer Reihe stehen?

10
Phrogz

Hier ist eine Middleware-Lösung, die von diese ausgezeichnete Antwort von @gertas modifiziert wurde. Diese Lösung ist nicht Rails spezifisch - sie sollte mit jeder Rack-Anwendung funktionieren.

Die hier verwendete Middleware-Technik unter Verwendung von #each wird unter ASCIIcasts 151: Rack Middleware von Eifion Bedford erläutert.

Dieser Code geht in 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

Zum Einschalten fügen Sie dies zu config/surroundings/test.rb und config/surroundings/development.rb hinzu:

config.middleware.use "PrettyJsonResponse"

Vermeiden Sie die Verwendung in der Produktion, da @gertas in seiner Version dieser Lösung warnt. Es ist etwas langsam.

Getestet mit Rails 4.1.6.

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

Ich habe den Edelstein CodeRay verwendet und es funktioniert ziemlich gut. Das Format enthält Farben und es werden viele verschiedene Formate erkannt.

Ich habe es für ein Juwel verwendet, das zum Debuggen von Rails-APIs verwendet werden kann, und es funktioniert ziemlich gut.

Der Edelstein heißt übrigens 'api_Explorer' ( http://www.github.com/toptierlabs/api_Explorer )

2
Tony

Wenn Sie dies schnell in einer Rails Controller-Aktion implementieren möchten, um eine JSON-Antwort zu senden:

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

Hier ist meine Lösung, die ich bei meiner eigenen Suche aus anderen Posts abgeleitet habe.

Auf diese Weise können Sie die pp- und jj-Ausgabe nach Bedarf in eine Datei senden.

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

Ich verwende das Folgende, da ich die Header, den Status und die JSON-Ausgabe als Satz nützlich finde. Die Aufrufroutine wird auf Empfehlung einer Railscast-Präsentation unter folgender Adresse aufgeschlüsselt: 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

Wenn Sie RABL verwenden, können Sie es wie beschrieben konfigurieren hier um JSON.pretty_generate zu verwenden:

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

Ein Problem bei der Verwendung von JSON.pretty_generate besteht darin, dass JSON-Schemaüberprüfungen nicht mehr mit Ihren datetime-Zeichenfolgen zufrieden sind. Sie können diese in Ihrer config/initializers/rabl_config.rb beheben mit:

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

Schöne Druckvariante:

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('=>', ': ')

Ergebnis:

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