ruby-on-rails - to_json - ruby json tostring




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

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

Jetzt rufe ich to_json und mein JSON ist alles in einer Zeile. Manchmal kann dies schwierig sein, wenn im JSON-Ausgabestream ein Problem auftritt.

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


Dank Rack Middleware und Rails 3 können Sie für jede Anfrage hübschen JSON ausgeben, ohne einen Controller Ihrer App zu ändern. Ich habe solch ein Middleware-Snippet geschrieben und ich bekomme schön gedruckten JSON in Browser und curl Ausgabe.

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 app/middleware/pretty_json_response.rb . 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 . Die JSON-Reparatur kann die Reaktionszeit und den Durchsatz Ihrer Produktions-App beeinträchtigen. Schließlich kann eine zusätzliche Logik, wie der "X-Pretty-Json: true" -Kopf, eingeführt werden, um die Formatierung für manuelle Aufrollungsanforderungen auf Anforderung auszulösen.

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


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

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

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

pp User.first.as_json

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

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

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

Dieser Code wird in app / middleware / pretty_json_response.rb angezeigt :

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

Um es einzuschalten, fügen Sie dies zu config / environments / test.rb und config / environments / development.rb hinzu:

config.middleware.use "PrettyJsonResponse"

Wie @gertas in seiner Version dieser Lösung warnt, vermeide es, es in der Produktion zu verwenden. Es ist etwas langsam.

Getestet mit Rails 4.1.6.


Ich benutze folgendes, da ich die Header, den Status und die JSON-Ausgabe als Set nützlich finde. Die Rufroutine ist auf Empfehlung einer Railscast-Präsentation unter http://railscasts.com/episodes/151-rack-middleware?autoplay=true ausgebrochen

  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

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

Ich habe es auf einem Juwel verwendet, das zum Debuggen von Rails-APIs verwendet werden kann, und es funktioniert ziemlich gut.

Das Juwel heißt übrigens 'api_explorer' ( http://www.github.com/toptierlabs/api_explorer )


Wenn Sie (wie ich) finden, dass die in der Ruby-JSON-Bibliothek pretty_generate Option pretty_generate nicht "hübsch" genug ist, empfehle ich NeatJSON mein eigenes NeatJSON Juwel für Ihre Formatierung.

Um es zu benutzen, gem install neatjson und verwende dann JSON.neat_generate statt JSON.pretty_generate .

Wie bei Rubys pp werden Objekte und Arrays auf einer Zeile gehalten, wenn sie passen, aber bei Bedarf zu mehreren Zeilen umbrechen. Beispielsweise:

{
  "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 unterstützt auch eine Vielzahl von Formatierungsoptionen , um Ihre Ausgabe weiter anzupassen. Zum Beispiel, wie viele Leerzeichen vor / nach Doppelpunkten? Vorher / Nachher Kommas? In Klammern von Arrays und Objekten? Möchten Sie die Schlüssel Ihres Objekts sortieren? Wollen Sie, dass die Doppelpunkte alle aneinandergereiht sind?


Wenn Sie RABL , können Sie es wie here beschrieben konfigurieren, 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 ist, dass JSON-Schema-Validatoren nicht mehr mit Ihren Datetime-Strings 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

Wenn du möchtest:

  1. Alle ausgehenden JSON-Antworten von Ihrer App automatisch prettieren
  2. Vermeiden Sie die Verschmutzung des Objekts # to_json / # as_json
  3. Vermeiden Sie es, JSON mit Middleware zu analysieren / neu zu rendern (YUCK!)
  4. Tun Sie es die Schienen Wege!

Dann ... ersetze den ActionController :: Renderer für JSON! Fügen Sie Ihrem ApplicationController 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

awesome_print . Analysiere die JSON-Zeichenfolge in einen Ruby-Hash und zeige sie dann mit awesome_print 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 dir nicht zeigt :)


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






pretty-print