Ruby漂亮的打印一个BSON文件?

Ruby pretty print a BSON document?

我正在使用 Ruby 在 MongoDB 中打印一个 BSON 文档。这是使用 MongoDB.

的 Ruby 包装器完成的
  client[:test].find().each do |doc|
    puts doc.to_json()
  end

查找方法returns一个BSON文件。这可以是 converted 使用 to_json 方法的字符串。

输出结果如下:

{"_id":{"$oid":"5a64d2ce36ab1f1ea4b06228"},"admin":"1234","users":"12345","house":{"a":0,"b":0,"c":0},"room":{"a":0,"b":2,"c":1}}

输出不是很可读。虽然我可能会使用一些正则表达式魔术将上面的字符串格式化为更易于理解的内容,但是否有更简单的方法可以将 BSON 文档很好地格式化为类似如下的格式:

_id: #
"admin": "1234"
"users": "12345"
"house":
  "a": 1
  "b": 2

我尝试了以下 Whosebug link。但是,答案为 attributes 产生了一个无方法错误,并且在注释之后用 keys 替换它之后只打印 keys,而不是 values .

虽然我以前没有使用过 mongodb 或 BSON,但如果我们从 JSON 的角度来看这个问题,您有几个选择。首先,不是调用 doc.to_json,而是使用方法 as_json 来获取哈希表示,然后将其转换为字符串,因此我们将使用 doc.as_json 作为起点点代替。

doc = {"_id":{"$oid":"5a64d2ce36ab1f1ea4b06228"},"admin":"1234","users":"12345","house":{"a":0,"b":0,"c":0},"room":{"a":0,"b":2,"c":1}}

第一种方法是使用 PP 库,它是 ruby:

的漂亮打印机
require 'pp'
pp doc
# Outputs:
# {:_id=>{:$oid=>"5a64d2ce36ab1f1ea4b06228"},
#  :admin=>"1234",
#  :users=>"12345",
#  :house=>{:a=>0, :b=>0, :c=>0},
#  :room=>{:a=>0, :b=>2, :c=>1}}

这与您想要的很接近,pp 库有一种方法可以通过在 class 中定义一个 #pretty_print(pp) 函数来定义自定义输出,您可以使用它来帮助完成剩下的工作。

要研究的第二个选项是 JSON.pretty_generate

require 'json'
puts JSON.pretty_generate(doc)
# {
#   "_id": {
#     "$oid": "5a64d2ce36ab1f1ea4b06228"
#   },
#   "admin": "1234",
#   "users": "12345",
#   "house": {
#     "a": 0,
#     "b": 0,
#     "c": 0
#   },
#   "room": {
#     "a": 0,
#     "b": 2,
#     "c": 1
#   }
# }

这更接近您的要求。通过一些 post-processing 你可以摆脱那些括号和逗号,如果你想:

puts JSON.pretty_generate(doc).delete('{},').gsub(/\n\s*\n/, "\n")

至于为什么从 attributes 切换到 keys 开始只输出 keys,好吧 attributes 看起来和听起来像是一个散列,因此循环每次都有 2 个元素传递给块, keys 听起来像一个数组,所以你只能得到属性的名称。如前所述,我不知道 mongo,但您随后需要以某种方式使用模型中指定的键查找属性以获取其值。例如,在 ActiveRecord 中,如果您无法使用其 attributes 方法,则可以使用 public_send(key)

使用 Awesome Print

将 BSON 转换为 Ruby 哈希后,您将有很多选择。其中之一是使用 Awesome Print gem 通过各种可配置选项漂亮地打印您的哈希对象。例如:

require 'awesome_print'

hash = {:_id=>{:$oid=>"5a64d2ce36ab1f1ea4b06228"},
        :admin=>"1234",
        :users=>"12345",
        :house=>{:a=>0, :b=>0, :c=>0},
        :room=>{:a=>0, :b=>2, :c=>1}}
ap h, indent: 2, index: false
{
    :_id => {
    :$oid => "5a64d2ce36ab1f1ea4b06228"
  },
  :admin => "1234",
  :users => "12345",
  :house => {
    :a => 0,
    :b => 0,
    :c => 0
  },
   :room => {
    :a => 0,
    :b => 2,
    :c => 1
  }
}

还要注意PP class for pretty printing is automatically loaded in Ruby 2.5.0。在某些情况下,pp some_hash 可能就是您所需要的。 YMMV.