漂亮打印哈希的最佳方法


169

我有一个带有嵌套数组和哈希的大型哈希。我想简单地将其打印出来,以使其对用户“可读”。

我希望它有点像to_yaml-可读性很强-但看上去还是高科技。

最终,最终用户将需要读取这些数据块,因此需要对它们进行干净的格式化。

有什么建议?



在线工具jsonviewer.stack.hu。但是,它不适用于哈希火箭语法。
阿米特·帕特尔

Answers:


256
require 'pp'
pp my_hash

使用pp如果你需要一个内置的解决方案,只是想合理的换行符。

如果可以安装gem,请使用awesome_print。(取决于您的用户,您可能希望使用该index:false选项来关闭显示数组索引。)


pp很不错,但是可惜不能限制深度。
akim

95

如果您拥有JSON,我建议您使用JSON.pretty_generate(hash)它,因为它比awesome_print更简单,在pre标签中看起来很棒,并且可以轻松地从Web页面进行复制。(另请参见:如何在Ruby on Rails中“漂亮”格式化JSON输出?


这个答案将受益于一个实际的例子
Travis Bear

@TravisBear如果您单击我的答案中的“另请参阅”链接,则会显示示例输出。我特别推荐这个答案:stackoverflow.com/a/1823885/109618
David J.

8
它将是puts JSON.pretty_generate(hash)
joeloui 2015年

如果确实需要创建JSON,请允许我推荐我自己的库(免费,OSS,无广告),用于从Ruby或JS创建漂亮的JSON:NeatJSON(Ruby)NeatJSON(Online / JS)
Phrogz

抱歉,我现在意识到pretty_generate确实接受Ruby对象,而不是json文本。
托尼

26

对我而言,另一种解决方案比pp或更好awesome_print

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

2
请注意,Pry::ColorPrinter.pp(obj)写入标准输出,但可以采用其他参数,包括目的地。喜欢Pry::ColorPrinter.pp(obj, a_logger)
Eric Urban

令我感到惊讶的是,它没有得到更好的记录:我一直将pry用作我的Rails控制台,并且很长一段时间以来,我一直在寻找如何在不使用其他gem的情况下利用其漂亮打印机的方法。由于此解决方案最终结束了我的漫长搜索,因此提出了建议。:-)
wiz

20

如果您没有任何奇特的gem操作,但是具有JSON,则此CLI行将适用于哈希:

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

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

  :key2 => "value2",

  :key3 => "value3"
}

8
投票不足,因为这会破坏包含“:”的所有键和值
thomax

1
这也不处理null(JSON)vs nil(Ruby)。
Rennex

1
在大多数情况下仍然方便。
艾布拉姆

1
三年后不敢相信!谢谢@Abram。:)这不是世界上最优雅的解决方案,但可以让您事半功倍。
尼克·史瓦德

4

如果要打印给用户,请使用上面的答案。

如果您只想在控制台中自己打印,建议您使用pry gem而不是irb。除了漂亮的打印效果外,pry还具有许多其他功能(请参见下面的railscast)

宝石安装撬

并检查此railscast:

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


3

如果您相信自己的键是理智的,那么使用JSON即可轻松实现:

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

使用Pry,您只需将以下代码添加到〜/ .pryrc中:

require "awesome_print"
AwesomePrint.pry!

1

在我尝试过的所有宝石中,show_data宝石对我来说效果最好,现在我几乎一直都在广泛使用它来在Rails中记录参数哈希


0

对于较大的嵌套哈希,此脚本可能对您有所帮助。它以漂亮的python / like语法打印嵌套的哈希,仅带有缩进以使其易于复制。

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

用法示例:

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

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

返回的值是嵌套哈希的所有最终值的计数(3)。


0

这是使用json和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))))

(解析来自的响应RestClient


0

在Rails中

如果你需要

  • 一个“漂亮打印”的哈希
  • 在例如Rails.logger
  • 具体来说, inspect是在哈希中的对象上
    • 如果您inspect应该像在对象中那样覆盖/定义对象中的方法,这将非常有用

...那么这很好用!(并且变得更好,您的Hash对象更大,更嵌套)。

logger.error my_hash.pretty_inspect

例如:

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_inspect来自PrettyPrint,默认情况下它包含在rails中。因此,不需要gem,也无需转换为JSON。

不在轨道上

如果您不在Rails中,或者由于某种原因上述操作失败,请尝试require "pp"先使用。例如:

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}

一个完整的例子

pretty_inspect我的项目中的Big ed Hash示例,其中删除了我检查的对象中特定于项目的文本:

{<***::******************[**:****, ************************:****]********* * ****** ******************** **** :: *********** - *** ******* *********>=>
  {: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

在Rails下,Ruby中的数组和哈希具有内置的to_json函数。我之所以使用JSON,是因为JSON在网络浏览器(例如Google Chrome)中非常易读。

话虽这么说,如果您担心它看起来太“高科技”,您可能应该编写自己的函数,用空格和其他字符替换散列和数组中的花括号和方括号。

查找gsub函数以找到一种非常好的方法。不断地使用不同的字符和不同数量的空格,直到找到有趣的东西为止。http://ruby-doc.org/core-1.9.3/String.html#method-i-gsub


7
数组和哈希没有内置的to_json方法,这些是由Rails的ActiveSupport添加的。
汤姆·德吕

它甚至比正常的irb / {"programming_language":{"ruby":{},"python":{}}}
pry

OP不排除Rails
Will Sheppard 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.