如何在YAML中读取ruby对象

时间:2018-03-12 12:01:48

标签: ruby yaml

我有一个YAML文件,如下所示:

--- !ruby/object:Hi
num: 1
--- !ruby/object:Hi
num: 2

和我的红宝石代码:

require 'yaml'
class A
 attr_accessor :num
 def initialize num
  @num=num
 end
end
a=A.new 1
b=A.new 2
File.open 'test.yml', 'r+' do |f|
 f.write YAML.dump a
 f.write YAML.dump b
 f.seek(0)
 #c=obj a
 #d=ojb b
end

我想让p c和p d输出如下:

#<A:0x00000 @num=1>
#<A:0x00001 @num=2>

3 个答案:

答案 0 :(得分:3)

我不确定为什么某些人如此坚定,因为YAML格式为explicitly designed to accommodate that particular use case,因此您不能将多个YAML文档放在一个文件中。在Ruby中,您可以使用YAML.load_stream解析多个文档,它将反序列化的对象作为数组返回:

require "yaml"

class A
  attr_accessor :num
  def initialize num
    @num = num
  end
end

a = A.new 1
b = A.new 2

File.open "test.yml", "r+" do |f|
  f.write YAML.dump(a)
  f.write YAML.dump(b)
  f.seek(0)

  c, d = YAML.load_stream(f)

  p c
  # => #<A:0x000055d423387cd0 @num=1>
  p d
  # => #<A:0x000055d423387528 @num=2>
end

您也可以将一个块传递给YAML.load_stream,在这种情况下,它会为每个文档调用:

YAML.load_stream(f) do |obj|
  p obj.num
end
# => 1
# => 2

您可以在repl.it:https://repl.it/@jrunning/FavorableElderlyAddition

中查看两者

答案 1 :(得分:-1)

我更喜欢将对象写入单独的文件,但您的序列化方式也可以。 以下是您案例的解决方案;

RUBY_OBJECT = '--- !ruby/object:'

def load_objects(file_content)
  object_contents = file_content.split(RUBY_OBJECT)

  object_contents.map do |object_content|
    YAML.load(RUBY_OBJECT + object_content)
  end.compact
end

##########

File.open 'test.yml', 'r+' do |f|
  f.write YAML.dump(a)
  f.write YAML.dump(b)

  f.seek(0)
  file_content = f.read
  c, d = *load_objects(file_content)

  puts c
  puts d
end

您还可以对文件内容运行regex以获取单个对象定义。

如果使用一个文件进行序列化是一项严格的要求,您可以像这样将一组对象序列化到该文件中;

require 'yaml'

class A
  attr_accessor :num

  def initialize(num)
    @num = num
  end
end

a = A.new(1)
b = A.new(2)

File.open('test.yml', 'w+') do |f|
  f.write YAML.dump([a, b])
end

objects = YAML.load_file('test.yml')

答案 2 :(得分:-2)

object = JSON.parse(YAML::load_file("./test.yaml").to_json, object_class: OpenStruct)

不是100%确定这些格式将会出现,但它会为您提供一个好的起点