วิธีที่ดีที่สุดในการพิมพ์แฮชสวย ๆ


169

ฉันมีแฮชขนาดใหญ่ที่มีอาร์เรย์ซ้อนกันและแฮช ฉันต้องการพิมพ์ออกมาเพื่อให้ผู้ใช้อ่านได้

ฉันต้องการให้เป็นเช่น to_yaml - อ่านได้สวย - แต่ยังดูเทคเกินไป

ในที่สุดมันก็จะเป็นผู้ใช้ที่ต้องอ่านข้อมูลเหล่านี้เพื่อให้พวกเขาจำเป็นต้องจัดรูปแบบได้อย่างหมดจด

ข้อเสนอแนะใด ๆ



ยูทิลิตี้ออนไลน์jsonviewer.stack.hu อย่างไรก็ตามมันไม่ทำงานอย่างถูกต้องสำหรับไวยากรณ์ของแฮชจรวด
Amit Patel

คำตอบ:


256
require 'pp'
pp my_hash

ใช้ppถ้าคุณต้องการโซลูชันในตัวและต้องการเพียงแค่ตัวแบ่งบรรทัดที่สมเหตุสมผล

ใช้Awesome_printหากคุณสามารถติดตั้งอัญมณี (ขึ้นอยู่กับผู้ใช้ของคุณคุณอาจต้องการใช้index:falseตัวเลือกเพื่อปิดการแสดงดัชนีอาร์เรย์)


pp เป็นคนดี แต่น่าเสียดายจริงๆที่ไม่มีใครจำกัดความลึกได้
Akim

95

หากคุณมี JSON ฉันขอแนะนำJSON.pretty_generate(hash)เพราะง่ายกว่าAwesome_printดูดีในpreแท็กและอนุญาตให้คัดลอกได้ง่ายจากหน้าเว็บ (ดูเพิ่มเติมที่: ฉันจะจัดรูปแบบ "สวย" เอาต์พุต JSON ของฉันใน Ruby on Rails ได้อย่างไร )


คำตอบนี้จะได้ประโยชน์จากตัวอย่างจริง
Travis Bear

@TravisBear มีเอาต์พุตตัวอย่างถ้าคุณคลิกลิงก์ "see also" ในคำตอบของฉัน ฉันแนะนำคำตอบนี้โดยเฉพาะ: stackoverflow.com/a/1823885/109618
David J.

8
มันจะเป็นputs JSON.pretty_generate(hash)
joeloui

หากคุณต้องการสร้าง JSON ให้ฉันแนะนำไลบรารีของฉันเอง (ฟรี, OSS, ไม่มีโฆษณา) สำหรับการสร้าง JSON ที่น่ารักจาก Ruby หรือ JS: 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)
เอริค Urban

ฉันประหลาดใจว่านี่ไม่ใช่เอกสารที่ดีกว่า: ฉันมักจะใช้แงะเป็นคอนโซล Rails ของฉันและฉันก็มองหาวิธีที่จะใช้เครื่องพิมพ์สวย ๆ เป็นเวลานานโดยไม่ต้องใช้อัญมณีอื่น โหวตขึ้นเพราะในที่สุดโซลูชันนี้ก็จบการค้นหาที่ยาวนานของฉัน :-)
Wiz

20

หากคุณไม่มีการกระทำอัญมณีแฟนซี แต่มี JSON บรรทัด CLI นี้จะทำงานบนแฮช:

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

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

  :key2 => "value2",

  :key3 => "value3"
}

8
Downvoted เพราะจะเลอะคีย์และค่าที่ประกอบด้วย ":"
thomax

1
สิ่งนี้ไม่เกี่ยวข้องกับ null (JSON) vs nil (Ruby)
Rennex

1
ยังคงมีประโยชน์สำหรับสถานการณ์ส่วนใหญ่
Abram

1
ไม่เชื่อในสามปีต่อมา! ขอบคุณ @Abram :) มันไม่ใช่ทางออกที่หรูหราที่สุดในโลก แต่ทำสิ่งต่าง ๆ ได้อย่างรวดเร็ว
Nick Schwaderer

4

ใช้คำตอบข้างต้นหากคุณกำลังพิมพ์ให้ผู้ใช้

หากคุณต้องการพิมพ์ด้วยตัวเองในคอนโซลฉันแนะนำให้ใช้ pry gem แทน irb นอกจากการพิมพ์ที่สวยงามแล้วแงะยังมีคุณสมบัติอื่น ๆ อีกมากมายเช่นกัน (ตรวจสอบทางรถไฟด้านล่าง)

ติดตั้งอัญมณีแงะ

และตรวจสอบรถไฟนี้:

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พลอยทำงานได้ดีที่สุดสำหรับฉันตอนนี้ฉันใช้มันอย่างกว้างขวางเพื่อล็อกแฮช params ใน Rails สวยตลอดเวลา


0

สำหรับแฮชซ้อนขนาดใหญ่สคริปต์นี้อาจมีประโยชน์สำหรับคุณ มันพิมพ์แฮชซ้อนใน python / like syntax ที่ดีโดยมีการเยื้องเพื่อให้ง่ายต่อการคัดลอก

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

ในทางรถไฟ

ถ้าคุณต้องการ

  • Hash "สวยพิมพ์"
  • ในเช่น Rails.logger
  • ที่เฉพาะเจาะจงทำงานinspectบนวัตถุในแฮ
    • ซึ่งมีประโยชน์หากคุณแทนที่ / กำหนดinspectวิธีการในวัตถุของคุณเหมือนที่คุณควรจะ

... ถ้าอย่างนั้นก็ใช้งานได้ดี! (และทำให้ดีขึ้นยิ่งวัตถุแฮชของคุณมีขนาดใหญ่ขึ้นและมากขึ้น)

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ซึ่งรางรวมถึงโดยค่าเริ่มต้น ดังนั้นไม่จำเป็นต้องใช้อัญมณีและไม่จำเป็นต้องแปลงเป็น JSON

ไม่ใช่ใน Rails

หากคุณไม่ได้อยู่ใน 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ตัวอย่างแฮชขนาดใหญ่จากโปรเจ็กต์ของฉันพร้อมข้อความเฉพาะโปรเจ็กต์จากวัตถุที่ตรวจสอบแล้วของฉันจะถูกทำซ้ำ:

{<***::******************[**:****, ************************:****]********* * ****** ******************** **** :: *********** - *** ******* *********>=>
  {: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 เพียงเพราะมันสามารถอ่านได้มากในเว็บเบราว์เซอร์เช่น Google Chrome

ที่ถูกกล่าวว่าถ้าคุณมีความกังวลเกี่ยวกับมันดูเกินไป "ดูเทคโนโลยี" คุณอาจจะเขียนฟังก์ชั่นของคุณเองที่แทนที่ปีกกาและวงเล็บปีกกาในแฮชและอาร์เรย์ของคุณด้วยพื้นที่สีขาวและตัวละครอื่น ๆ

ค้นหาฟังก์ชั่น gsub เพื่อหาวิธีที่ดีมากในการทำมัน เล่นต่อไปเรื่อย ๆ ด้วยตัวละครที่แตกต่างกันและพื้นที่ว่างที่แตกต่างกันจนกว่าคุณจะพบสิ่งที่ดูน่าสนใจ http://ruby-doc.org/core-1.9.3/String.html#method-i-gsub


7
อาร์เรย์และแฮชไม่มีเมธอด to_json ในตัวซึ่งจะเพิ่มโดย ActiveSupport จาก Rails
Tom De Leu

มันเลวร้ายยิ่งกว่า irb / pry ปกติ:{"programming_language":{"ruby":{},"python":{}}}
Darek Nędza

OP ไม่ได้ออกกฎ Rails
Will Sheppard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.