Comment puis-je" pretty " formater ma sortie JSON en Ruby on Rails?

j'aimerais que ma sortie JSON dans Ruby on Rails soit" jolie " ou joliment formatée.

en ce moment, j'appelle to_json et mon JSON est sur une seule ligne. Parfois, cela peut être difficile de voir s'il y a un problème dans le flux de sortie JSON.

y a-t-il moyen de configurer ou une méthode pour rendre mon JSON" joli " ou joliment formaté dans les Rails?

535
demandé sur the Tin Man 2008-09-17 23:25:17

16 réponses

utilise la fonction pretty_generate() , intégrée dans les versions ultérieures de JSON. Par exemple:

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

Qui vous permet de vous:

{
  "array": [
    1,
    2,
    3,
    {
      "sample": "hash"
    }
  ],
  "foo": "bar"
}
859
répondu jpatokal 2016-07-25 22:33:27

merci à Rack Middleware et Rails 3 vous pouvez produire pretty JSON pour chaque demande sans changer n'importe quel contrôleur de votre application. J'ai écrit un tel middleware snippet et je reçois JSON joliment imprimé dans le navigateur et curl sortie.

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

le code ci-dessus doit être placé dans app/middleware/pretty_json_response.rb de votre projet Rails. Et la dernière étape est d'enregistrer le middleware dans config/environments/development.rb :

config.middleware.use PrettyJsonResponse

je n'ai pas il est recommandé de l'utiliser dans production.rb . La réparation JSON peut dégrader le temps de réponse et le débit de votre application de production. Éventuellement, une logique supplémentaire telle que l'en-tête 'X-Pretty-JSON: true' peut être introduite pour déclencher le formatage des requêtes curl manuelles à la demande.

(Testé avec les Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux)

68
répondu gertas 2016-09-10 20:25:21

la balise <pre> en HTML, utilisée avec JSON.pretty_generate , rendra le JSON pretty à votre avis. J'étais tellement heureux quand mon illustre patron m'a montré ceci:

<% if !@data.blank? %>
   <pre><%= JSON.pretty_generate(@data) %></pre>
<% end %>
59
répondu Roger Garza 2013-11-27 01:47:31

si vous voulez:

  1. Prétifiez toutes les réponses JSON sortantes de votre application automatiquement.
  2. éviter de polluer L'objet # to_json / # as_json
  3. éviter d'analyser / re-rendre JSON en utilisant middleware (YUCK!)
  4. Faire les RAILS de CHEMIN!

alors ... remplacer le contrôleur ActionController:: Renderer pour JSON! Il suffit d'ajouter le code suivant à votre ApplicationController:

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
répondu Ed Lebert 2014-04-11 16:42:29

Check out awesome_print . Analysez la chaîne JSON en un Hash Ruby, puis affichez-le avec awesome_print comme suit:

require "awesome_print"
require "json"

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

ap(JSON.parse(json))

avec ce qui précède, vous verrez:

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

awesome_print va aussi ajouter une couleur que le débordement de la pile ne vous montrera pas:)

10
répondu Synthead 2016-12-02 19:39:31

largage D'un objet ActiveRecord à JSON (dans la console Rail):

pp User.first.as_json

# => {
 "id" => 1,
 "first_name" => "Polar",
 "last_name" => "Bear"
}
9
répondu Thomas Klemm 2014-04-04 13:31:48

si vous (comme moi) trouvez que l'option pretty_generate intégrée dans la bibliothèque JSON de Ruby n'est pas" assez", je recommande ma propre pierre NeatJSON pour votre formatage.

pour l'utiliser gem install neatjson et ensuite utiliser JSON.neat_generate au lieu de JSON.pretty_generate .

comme pp de Ruby, il gardera les objets et les tableaux sur une seule ligne quand ils conviennent, mais les enveloppera à plusieurs si nécessaire. Par exemple:

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

il supporte également une variété de options de formatage pour personnaliser davantage votre sortie. Par exemple, combien d'espaces avant/après les virgules? Avant / après virgule? Dans les consoles des tableaux et des objets? Voulez-vous trier les clés de votre objet? Tu veux que les colons soient alignés?

9
répondu Phrogz 2015-04-16 16:01:09

utilisant <pre> code html et pretty_generate est un bon truc:

<%
  require 'json'

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

<pre>
  <%=  JSON.pretty_generate(hash) %>
</pre>
9
répondu araratan 2016-08-03 01:50:54

Voici une solution middleware modifiée de cette excellente réponse de @gertas . Cette solution n'est pas spécifique aux Rails, elle devrait fonctionner avec n'importe quelle application de crémaillère.

la technique middleware utilisée ici, en utilisant #each, est expliquée à ASCIIcasts 151: Rack Middleware par Eifion Bedford.

ce code va dans 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

pour l'allumer, ajoutez ceci à config/environments/test.rb et config/environments/développement.rb:

config.middleware.use "PrettyJsonResponse"

comme avertit @gertas dans sa version de cette solution, éviter de l'utiliser dans la production. C'est un peu lent.

éprouvé avec des Rails 4.1.6.

6
répondu Wayne Conrad 2017-05-23 12:02:47
#At Controller
def branch
    @data = Model.all
    render json: JSON.pretty_generate(@data.as_json)
end
4
répondu Буянбат Чойжилсүрэн 2017-05-16 11:43:24

voici ma solution que j'ai dérivé d'autres messages au cours de ma propre recherche.

cela vous permet d'envoyer la sortie pp et jj dans un fichier au besoin.

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
répondu Christopher Mullins 2012-12-23 04:01:27

j'ai utilisé le Gem CodeRay et il fonctionne assez bien. Le format comprend des couleurs et il reconnaît beaucoup de formats différents.

Je l'ai utilisé sur un bijou qui peut être utilisé pour déboguer les API rails et il fonctionne assez bien.

soit dit en passant, le joyau s'appelle "api_explorer" ( http://www.github.com/toptierlabs/api_explorer )

2
répondu Tony 2013-11-21 22:08:20

si vous cherchez à implémenter rapidement cette action dans un contrôleur rail pour envoyer une réponse JSON:

def index
  my_json = '{ "key": "value" }'
  render json: JSON.pretty_generate( JSON.parse my_json )
end
2
répondu sealocal 2016-02-17 00:38:07

j'utilise ce qui suit car je trouve les en-têtes, le statut et la sortie JSON utiles comme ensemble. La routine d'appel est débitée sur recommandation d'une présentation railscasts à: 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
répondu TheDadman 2014-04-01 04:05:39

si vous utilisez RABL vous pouvez configurer comme décrit ici pour utiliser JSON.pretty_generate:

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

un problème avec L'utilisation de JSON.pretty_generate est que les validateurs de schéma JSON ne seront plus satisfaits de vos chaînes datetime. Vous pouvez les corriger dans votre config/initializers/rabl_config.rb avec:

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
répondu Jim Flood 2015-09-04 18:03:30

# 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
répondu Sergio Belevskij 2015-11-30 07:15:54