Frage

Ich möchte, dass meine JSON-Ausgabe in Ruby on Rails „hübsch“ oder gut formatiert ist.

Im Moment rufe ich an to_json und mein JSON ist alles in einer Zeile.Manchmal kann es schwierig sein, ein Problem im JSON-Ausgabestream zu erkennen.

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

War es hilfreich?

Lösung

Mit der pretty_generate() Funktion, in späteren Versionen von JSON gebaut. Zum Beispiel:

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

Welche bekommt man:

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

Andere Tipps

Dank Rack-Middleware und Rails 3 können Sie die Ausgabe ziemlich JSON für jede Anfrage ohne jede Steuerung Ihrer Anwendung zu ändern. Ich habe solche Middleware-Schnipsel geschrieben und ich bekomme schön JSON in Browser und curl Ausgabe 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 Ihrem Rails-Projekt platziert werden. Und der letzte Schritt ist die Middleware in config/environments/development.rb registrieren:

config.middleware.use PrettyJsonResponse

Ich empfehle nicht, es in production.rb zu verwenden . Die JSON neuparsen kann die Reaktionszeit und Durchsatz Ihrer Produktions App verschlechtern. Schließlich zusätzliche Logik wie ‚X-Pretty-Json: true‘. Header eingeführt werden kann, die Formatierung für die manuellen curl Anfragen auf Anfrage auslösen

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

Das <pre>-Tag in HTML, mit JSON.pretty_generate verwendet, wird die JSON ziemlich Ihrer Ansicht nach machen. Ich war so glücklich, als mein berühmter Chef zeigte mir dies:

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

Wenn Sie wollen:

  1. Prettify alle abgehenden JSON Antworten von Ihrer Anwendung automatisch.
  2. Vermeiden Objekt # to_json verschmutzen / # as_json
  3. Vermeiden Parsing / Re-Rendering JSON mit Middleware (igitt!)
  4. Machen Sie es den Schienen WAY!

Dann ... ersetzen Sie die Action :: Renderer für JSON! Fügen Sie einfach den folgenden Code auf Ihre Application:

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

Schauen Sie sich awesome_print . Analysieren Sie den JSON-String in einen Ruby-Hash, es zeigt dann mit awesome_print etwa so:

require "awesome_print"
require "json"

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

ap(JSON.parse(json))

Mit dem oben, sehen Sie:

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

awesome_print fügt auch etwas Farbe, die Stack-Überlauf wird nicht zeigen:)

Dumping ein Activerecord-Objekt JSON (in der Rails-Konsole):

pp User.first.as_json

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

Wenn Sie (wie ich) finden, dass die pretty_generate Option in Rubys JSON Bibliothek gebaut ist nicht „schön“ genug, empfehle ich meine eigene NeatJSON Juwel für Ihre Formatierung.

Um es zu nutzen gem install neatjson und verwenden Sie dann JSON.neat_generate statt JSON.pretty_generate.

Wie Rubys pp es Objekte und Arrays auf einer Linie halten, wenn sie passen, aber wickelt, um mehr nach Bedarf. 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 unterstützt auch eine Vielzahl von Formatierungsoptionen um Ihre Ausgabe anpassen. Zum Beispiel, wie viele Leerzeichen vor / nach Doppelpunkten? Vorher / Nachher Komma? Innerhalb der Klammern von Arrays und Objekte? Wollen Sie die Tasten Ihres Objekts sortieren? Wollen Sie die Doppelpunkte auf alle aufgereiht werden?

Mit <pre> HTML-Code und pretty_generate ist 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>

Hier ist eine Middleware-Lösung von Antwort dieser ausgezeichneten geändert durch @gertas . Diese Lösung ist nicht Rails spezifisch -. Es sollte mit jeder Rack-Anwendung arbeitet

Die Middleware-Technik hier verwendet wird, #each verwendet wird, wird erklärt unter ASCIIcasts 151: Rack-Middleware von Eifion Bedford.

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 diese config / Umgebungen / test.rb und config / Umgebungen / development.rb:

config.middleware.use "PrettyJsonResponse"

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

Getestet mit Rails 4.1.6.

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

Hier ist meine Lösung, die ich von anderen Beiträgen während meiner eigenen Suche abgeleitet.

Auf diese Weise können Sie die Seiten und jj Ausgabe in eine Datei senden, je nach Bedarf.

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

Ich habe das Gem CodeRay verwendet und es funktioniert ziemlich gut.Das Format umfasst Farben und erkennt viele verschiedene Formate.

Ich habe es auf einem Gem 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)

Wenn Sie schauen, um schnell diese in einer Aktion Rails-Controller implementieren eine JSON-Antwort zu senden:

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

Ich benutze das folgende, wie ich die Header, Status und JSON Ausgabe nützlich als ein Satz. Der Aufruf Routine wird ausgebrochenen auf Empfehlung einer Railscasts Präsentation unter: http: // Railscasts .com / Episoden / 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

Wenn Sie mit RABL können Sie es so konfigurieren, wie beschrieben hier 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 JSON.pretty_generate ist, dass JSON Schema Validatoren nicht mehr mit Ihren Datetime Strings glücklich sein. Sie können die in Ihrem config / initializers / rabl_config.rb fix 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

# 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

Pretty 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}}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top