Il modo migliore per stampare graziosamente un hash


169

Ho un grande hash con array e hash nidificati. Vorrei semplicemente stamparlo in modo che sia "leggibile" per l'utente.

Vorrei che fosse in qualche modo to_yaml - è abbastanza leggibile - ma sembra ancora troppo tecnologico.

Alla fine saranno gli utenti finali a dover leggere questi blocchi di dati, quindi devono essere formattati in modo pulito.

Eventuali suggerimenti?



utilità online jsonviewer.stack.hu . Tuttavia non funziona correttamente per la sintassi del razzo hash.
Amit Patel,

Risposte:


256
require 'pp'
pp my_hash

Utilizzare ppse si necessita di una soluzione integrata e si desiderano solo interruzioni di linea ragionevoli.

Usa awesome_print se puoi installare una gemma. (A seconda degli utenti, è possibile utilizzare l' index:falseopzione per disattivare la visualizzazione degli indici di array.)


la pp è bella, ma è davvero un peccato non poterne limitare la profondità.
Akim

95

Se hai JSON, ti consiglio JSON.pretty_generate(hash)perché è più semplice di awesome_print , ha un bell'aspetto in un pretag e consente una facile copia da una pagina web. (Vedi anche: Come posso "grazioso" formattare il mio output JSON in Ruby on Rails? )


Questa risposta trarrebbe beneficio da un esempio reale
Travis Bear,

@TravisBear C'è un esempio di output se fai clic sul link "vedi anche" nella mia risposta. Raccomando questa risposta in particolare: stackoverflow.com/a/1823885/109618
David J.

8
Sarebbeputs JSON.pretty_generate(hash)
joeloui,

Se hai bisogno di creare JSON, permettimi di consigliare la mia libreria (gratuita, OSS, senza pubblicità) per creare graziosi JSON da Ruby o JS: NeatJSON (Ruby) e NeatJSON (Online / JS)
Phrogz

Mi spiace, mi rendo conto ora che pretty_generate accetta un oggetto Ruby, non un testo json.
Tony,

26

Un'altra soluzione che funziona meglio per me di ppo awesome_print:

require 'pry' # must install the gem... but you ALWAYS want pry installed anyways
Pry::ColorPrinter.pp(obj)

2
Si noti che Pry::ColorPrinter.pp(obj)scrive su standard out ma può accettare parametri aggiuntivi, inclusa la destinazione. Mi piacePry::ColorPrinter.pp(obj, a_logger)
Eric Urban

Sono sorpreso che questo non sia meglio documentato: uso sempre leva come mia console Rails e ho cercato a lungo come sfruttare la sua bella stampante senza usare un'altra gemma. È stato votato perché questa soluzione ha finalmente messo fine alla mia lunga ricerca. :-)
wiz

20

Se non hai alcuna azione gemma di fantasia, ma hai JSON, questa riga della CLI funzionerà su un hash:

puts JSON.pretty_generate(my_hash).gsub(":", " =>")

#=>
{
  :key1 => "value1",

  :key2 => "value2",

  :key3 => "value3"
}

8
Sottovalutato perché ciò rovinerà qualsiasi chiave e valore contenente ":"
thomax

1
Anche questo non riguarda null (JSON) vs zero (Ruby).
Rennex,

1
Ancora utile per la maggior parte delle situazioni.
Abram,

1
Non ci posso credere tre anni dopo! Grazie @Abram. :) Non è la soluzione più elegante del mondo, ma fa le cose in un attimo.
Nick Schwaderer,

4

Usa le risposte sopra se stai stampando per gli utenti.

Se vuoi solo stamparlo da solo in console, ti suggerisco di usare la gemma di leva invece di irb. Oltre alla bella stampa, pry ha anche molte altre funzioni (controlla railscast sotto)

gem install pry

E controlla questo railscast:

http://railscasts.com/episodes/280-pry-with-rails


3

Facile da fare con JSON se ritieni che le tue chiavi siano sane:

JSON.pretty_generate(a: 1, 2 => 3, 3 => nil).
  gsub(": null", ": nil").
  gsub(/(^\s*)"([a-zA-Z][a-zA-Z\d_]*)":/, "\\1\\2:"). # "foo": 1 -> foo: 1
  gsub(/(^\s*)(".*?"):/, "\\1\\2 =>") # "123": 1 -> "123" => 1

{
  a: 1,
  "2" => 3,
  "3" => nil
}

1

Usando Pry devi solo aggiungere il seguente codice al tuo ~ / .pryrc:

require "awesome_print"
AwesomePrint.pry!

1

Di tutte le gemme che ho provato, show_datagemma ha funzionato al meglio per me, ora lo uso ampiamente per registrare l'hash params in Rails praticamente tutto il tempo


0

Per hash nidificati di grandi dimensioni questo script potrebbe essere utile per te. Stampa un hash nidificato in una bella sintassi python / like con solo rientri per facilitarne la copia.

module PrettyHash
  # Usage: PrettyHash.call(nested_hash)
  # Prints the nested hash in the easy to look on format
  # Returns the amount of all values in the nested hash

  def self.call(hash, level: 0, indent: 2)
    unique_values_count = 0
    hash.each do |k, v|
      (level * indent).times { print ' ' }
      print "#{k}:"
      if v.is_a?(Hash)
        puts
        unique_values_count += call(v, level: level + 1, indent: indent)
      else
        puts " #{v}"
        unique_values_count += 1
      end
    end
    unique_values_count
  end
end

Esempio di utilizzo:

  h = {a: { b: { c: :d }, e: :f }, g: :i }
  PrettyHash.call(h)

a:
  b:
    c: d
  e: f
g: i
=> 3

Il valore restituito è il conteggio (3) di tutti i valori di livello finale dell'hash nidificato.


0

Ecco un altro approccio che utilizza json e rouge:

require 'json'
require 'rouge'

formatter = Rouge::Formatters::Terminal256.new
json_lexer = Rouge::Lexers::JSON.new

puts formatter.format(json_lexer.lex(JSON.pretty_generate(JSON.parse(response))))

(analizza la risposta ad es. RestClient)


0

In Rails

Se hai bisogno

  • un hash "piuttosto stampato"
  • ad esempio in Rails.logger
  • che, in particolare, viene eseguito inspectsugli oggetti nell'hash
    • che è utile se sostituisci / definisci il inspectmetodo nei tuoi oggetti come dovresti

... allora funziona alla grande! (E migliora, più grande e nidificato è il tuo oggetto Hash.)

logger.error my_hash.pretty_inspect

Per esempio:

class MyObject1
  def inspect
    "<#{'*' * 10} My Object 1 #{'*' * 10}>"
  end
end

class MyObject2
  def inspect
    "<#{'*' * 10} My Object 2 #{'*' * 10}>"
  end
end

my_hash = { a: 1, b: MyObject1.new, MyObject2.new => 3 }

Rails.logger.error my_hash
# {:a=>1, :b=><********** My Object 1 **********>, <********** My Object 2 **********>=>3}

# EW! ^

Rails.logger.error my_hash.pretty_inspect
# {:a=>1,
#  :b=><********** My Object 1 **********>,
#  <********** My Object 2 **********>=>3}

pretty_inspectproviene da PrettyPrint , che include rotaie per impostazione predefinita. Quindi, non sono necessarie gemme e nessuna conversione in JSON necessaria.

Non in rotaie

Se non sei in Rails o se per qualche motivo non si verifica quanto sopra, prova a utilizzare require "pp"prima. Per esempio:

require "pp"  # <-----------

class MyObject1
  def inspect
    "<#{'*' * 10} My Object 1 #{'*' * 10}>"
  end
end

class MyObject2
  def inspect
    "<#{'*' * 10} My Object 2 #{'*' * 10}>"
  end
end

my_hash = { a: 1, b: MyObject1.new, MyObject2.new => 3 }

puts my_hash
# {:a=>1, :b=><********** My Object 1 **********>, <********** My Object 2 **********>=>3}

# EW! ^

puts my_hash.pretty_inspect
# {:a=>1,
#  :b=><********** My Object 1 **********>,
#  <********** My Object 2 **********>=>3}

Un esempio completo

pretty_inspectEsempio di Big ol ' ed Hash del mio progetto con testo specifico del progetto dai miei oggetti ispezionati redatto:

{<***::******************[**:****, ************************:****]********* * ****** ******************** **** :: *********** - *** ******* *********>=>
  {:errors=>
    ["************ ************ ********** ***** ****** ******** ***** ****** ******** **** ********** **** ***** ***** ******* ******",
     "************ ************ ********** ***** ****** ******** ***** ****** ******** **** ********** is invalid",
     "************ ************ ********** ***** ****** ******** is invalid",
     "************ ************ ********** is invalid",
     "************ ************ is invalid",
     "************ is invalid"],
   :************=>
    [{<***::**********[**:****, *************:**, ******************:*, ***********************:****] :: **** **** ****>=>
       {:************=>
         [{<***::***********[**:*****, *************:****, *******************:**]******* :: *** - ******* ***** - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: *** - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ********* - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ********** - ********** *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ******** - *>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: **** - *******>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: *** - ********** ***** - *>=>
            {}}]}},
     {<***::**********[**:****, *************:**, ******************:*, ***********************:****] ******************** :: *** - *****>=>
       {:errors=>
         ["************ ********** ***** ****** ******** ***** ****** ******** **** ********** **** ***** ***** ******* ******",
          "************ ********** ***** ****** ******** ***** ****** ******** **** ********** is invalid",
          "************ ********** ***** ****** ******** is invalid",
          "************ ********** is invalid",
          "************ is invalid"],
        :************=>
         [{<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - ********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - ********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *******>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]*********** :: ****>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *******>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *******>=>
            {:errors=>
              ["********** ***** ****** ******** ***** ****** ******** **** ********** **** ***** ***** ******* ******",
               "********** ***** ****** ******** ***** ****** ******** **** ********** is invalid",
               "********** ***** ****** ******** is invalid",
               "********** is invalid"],
             :**********************=>
              [{<***::*******************[**:******, ************************:***]****-************ ******************** ***: * :: *** - ***** * ****** ** - ******* * **: *******>=>
                 {:errors=>
                   ["***** ****** ******** **** ********** **** ***** ***** ******* ******",
                    "***** ****** ******** **** ********** is invalid"],
                  :***************=>
                   [{<***::********************************[**:******, *************:******, ***********:******, ***********:"************ ************"]** * *** * ****-******* * ******** * ********* ******************** *********************: ***** :: "**** *" -> "">=>
                      {:errors=>["**** ***** ***** ******* ******"],
                       :**********=>
                        {<***::*****************[**:******, ****************:["****** ***", "****** ***", "****** ****", "******* ***", "******* ****", "******* ***", "****"], **:""] :: "**** *" -> "">=>
                          {:errors=>
                            ["***** ******* ******",
                             "***** ******* ******"]}}}}]}}]}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:**]******* :: ****** - ** - *********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - ********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - **********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - **********>=>
            {}},
          {<***::***********[**:*****, *************:****, *******************:***]******* :: ****** - ** - **********>=>
            {}}]}}]}}

-4

In Rails, le matrici e gli hash in Ruby hanno funzioni to_json integrate. Vorrei utilizzare JSON solo perché è molto leggibile all'interno di un browser Web, ad esempio Google Chrome.

Detto questo, se sei preoccupato che appaia troppo "dall'aspetto tecnologico", probabilmente dovresti scrivere la tua funzione che sostituisce le parentesi graffe e le parentesi quadre nei tuoi hash e array con spazi bianchi e altri personaggi.

Cerca la funzione gsub per un ottimo modo per farlo. Continua a giocare con personaggi diversi e diverse quantità di spazi bianchi fino a trovare qualcosa di attraente. http://ruby-doc.org/core-1.9.3/String.html#method-i-gsub


7
Le matrici e gli hash non hanno un metodo to_json incorporato, questi vengono aggiunti da ActiveSupport da Rails.
Tom De Leu,

È anche peggio del normale irb / leva:{"programming_language":{"ruby":{},"python":{}}}
Darek Nędza il

OP non ha escluso Rails
Will Sheppard il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.