模块 Psych
概述¶ ↑
Psych 是一个 YAML 解析器和生成器。Psych 利用 libyaml [主页:pyyaml.org/wiki/LibYAML] 或 [git 仓库:github.com/yaml/libyaml] 来进行其 YAML 解析和生成功能。除了封装 libyaml 之外,Psych 还知道如何将大多数 Ruby 对象序列化和反序列化为 YAML 格式。
我需要立即解析或生成 YAML!¶ ↑
# Parse some YAML Psych.load("--- foo") # => "foo" # Emit some YAML Psych.dump("foo") # => "--- foo\n...\n" { :a => 'b'}.to_yaml # => "---\n:a: b\n"
有更多时间吗?继续阅读!
YAML 解析¶ ↑
Psych 提供了多种用于解析 YAML 文档的接口,从低级到高级,具体取决于您的解析需求。在最低级别,是一个基于事件的解析器。中级可以访问原始的 YAML AST,在最高级别,可以将 YAML 反序列化为 Ruby 对象。
YAML 生成¶ ↑
Psych 提供了多种接口,从低级到高级,用于生成 YAML 文档。与 YAML 解析接口非常相似,Psych 在最低级别提供基于事件的系统,中级是构建 YAML AST,最高级别是将 Ruby 对象直接转换为 YAML 文档。
高级 API¶ ↑
解析¶ ↑
Psych 提供的高级 YAML 解析器只是将 YAML 作为输入并返回一个 Ruby 数据结构。有关使用高级解析器的信息,请参阅 Psych.load
从字符串读取¶ ↑
Psych.safe_load("--- a") # => 'a' Psych.safe_load("---\n - a\n - b") # => ['a', 'b'] # From a trusted string: Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
从文件读取¶ ↑
Psych.safe_load_file("data.yml", permitted_classes: [Date]) Psych.load_file("trusted_database.yml")
异常处理¶ ↑
begin # The second argument changes only the exception contents Psych.parse("--- `", "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
生成¶ ↑
高级生成器具有最简单的接口。Psych 只是接收一个 Ruby 数据结构并将其转换为 YAML 文档。有关转储 Ruby 数据结构的更多信息,请参阅 Psych.dump。
写入字符串¶ ↑
# Dump an array, get back a YAML string Psych.dump(['a', 'b']) # => "---\n- a\n- b\n" # Dump an array to an IO object Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890> # Dump an array with indentation set Psych.dump(['a', ['b']], :indentation => 3) # => "---\n- a\n- - b\n" # Dump an array to an IO with indentation set Psych.dump(['a', ['b']], StringIO.new, :indentation => 3)
写入文件¶ ↑
目前没有直接的 API 用于将 Ruby 结构转储到文件
File.open('database.yml', 'w') do |file| file.write(Psych.dump(['a', 'b'])) end
中级 API¶ ↑
解析¶ ↑
Psych 提供了访问从解析 YAML 文档生成的 AST 的功能。这个树是使用 Psych::Parser 和 Psych::TreeBuilder 构建的。可以自由地检查和操作 AST。有关处理 YAML 语法树的更多信息,请参阅 Psych::parse_stream、Psych::Nodes 和 Psych::Nodes::Node。
从字符串读取¶ ↑
# Returns Psych::Nodes::Stream Psych.parse_stream("---\n - a\n - b") # Returns Psych::Nodes::Document Psych.parse("---\n - a\n - b")
从文件读取¶ ↑
# Returns Psych::Nodes::Stream Psych.parse_stream(File.read('database.yml')) # Returns Psych::Nodes::Document Psych.parse_file('database.yml')
异常处理¶ ↑
begin # The second argument changes only the exception contents Psych.parse("--- `", "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
生成¶ ↑
在中级,是构建 AST。此 AST 与解析 YAML 文档时使用的 AST 完全相同。用户可以手动构建 AST,并且 AST 知道如何将其自身作为 YAML 文档发出。有关构建 YAML AST 的更多信息,请参阅 Psych::Nodes、Psych::Nodes::Node 和 Psych::TreeBuilder。
写入字符串¶ ↑
# We need Psych::Nodes::Stream (not Psych::Nodes::Document) stream = Psych.parse_stream("---\n - a\n - b") stream.to_yaml # => "---\n- a\n- b\n"
写入文件¶ ↑
# We need Psych::Nodes::Stream (not Psych::Nodes::Document) stream = Psych.parse_stream(File.read('database.yml')) File.open('database.yml', 'w') do |file| file.write(stream.to_yaml) end
低级 API¶ ↑
解析¶ ↑
当 YAML 输入已知,并且开发人员不想付出构建 AST 或自动检测和转换为 Ruby 对象的代价时,应使用最低级别的解析器。有关使用基于事件的解析器的更多信息,请参阅 Psych::Parser。
读取到 Psych::Nodes::Stream 结构¶ ↑
parser = Psych::Parser.new(TreeBuilder.new) # => #<Psych::Parser> parser = Psych.parser # it's an alias for the above parser.parse("---\n - a\n - b") # => #<Psych::Parser> parser.handler # => #<Psych::TreeBuilder> parser.handler.root # => #<Psych::Nodes::Stream>
接收事件流¶ ↑
recorder = Psych::Handlers::Recorder.new parser = Psych::Parser.new(recorder) parser.parse("---\n - a\n - b") recorder.events # => [list of [event, args] lists] # event is one of: Psych::Handler::EVENTS # args are the arguments passed to the event
生成¶ ↑
最低级别的生成器是基于事件的系统。事件被发送到 Psych::Emitter 对象。该对象知道如何将事件转换为 YAML 文档。当预先知道文档格式或需要考虑速度时,应使用此接口。有关更多信息,请参阅 Psych::Emitter。
写入 Ruby 结构¶ ↑
Psych.parser.parse("--- a") # => #<Psych::Parser> parser.handler.first # => #<Psych::Nodes::Stream> parser.handler.first.to_ruby # => ["a"] parser.handler.root.first # => #<Psych::Nodes::Document> parser.handler.root.first.to_ruby # => "a" # You can instantiate an Emitter manually Psych::Visitors::ToRuby.new.accept(parser.handler.root.first) # => "a"
常量
公共类方法
源代码
# File ext/psych/lib/psych.rb, line 515 def self.dump o, io = nil, options = {} if Hash === io options = io io = nil end visitor = Psych::Visitors::YAMLTree.create options visitor << o visitor.tree.yaml io, options end
将 Ruby 对象 o 转储为 YAML 字符串。可以传入可选的 options 以控制输出格式。如果传入 IO 对象,则 YAML 将转储到该 IO 对象。
当前支持的选项有
:indentation-
用于缩进的空格字符数。可接受的值应在
0..9范围内,否则将忽略该选项。默认值:
2。 :line_width-
换行的最大字符数。对于无限行宽,请使用
-1。默认值:
0(表示“在 81 处换行”)。 :canonical-
写入“规范”
YAML形式(非常冗长,但严格正式)。默认值:
false。 :header-
在文档开头写入
%YAML [version]。默认值:
false。 :stringify_names-
将
Hash对象中的符号键转储为字符串。默认值:
false。
示例
# Dump an array, get back a YAML string Psych.dump(['a', 'b']) # => "---\n- a\n- b\n" # Dump an array to an IO object Psych.dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890> # Dump an array with indentation set Psych.dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n" # Dump an array to an IO with indentation set Psych.dump(['a', ['b']], StringIO.new, indentation: 3) # Dump hash with symbol keys as string Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
源代码
# File ext/psych/lib/psych.rb, line 613 def self.dump_stream *objects visitor = Psych::Visitors::YAMLTree.create({}) objects.each do |o| visitor << o end visitor.tree.yaml end
将对象列表作为单独的文档转储到文档流中。
示例
Psych.dump_stream("foo\n ", {}) # => "--- ! \"foo\\n \"\n--- {}\n"
源代码
static VALUE libyaml_version(VALUE module)
{
int major, minor, patch;
VALUE list[3];
yaml_get_version(&major, &minor, &patch);
list[0] = INT2NUM(major);
list[1] = INT2NUM(minor);
list[2] = INT2NUM(patch);
return rb_ary_new4((long)3, list);
}
返回正在使用的 libyaml 版本
源代码
# File ext/psych/lib/psych.rb, line 370 def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false safe_load yaml, permitted_classes: permitted_classes, permitted_symbols: permitted_symbols, aliases: aliases, filename: filename, fallback: fallback, symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer end
将 yaml 加载到 Ruby 数据结构中。如果提供了多个文档,将返回第一个文档中包含的对象。如果解析时引发任何异常,则 filename 将用于异常消息中。如果 yaml 为空,则返回指定的 fallback 返回值,默认为 nil。
当检测到 YAML 语法错误时,会引发 Psych::SyntaxError。
示例
Psych.load("--- a") # => 'a' Psych.load("---\n - a\n - b") # => ['a', 'b'] begin Psych.load("--- `", filename: "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
当可选的 symbolize_names 关键字参数设置为 true 值时,将返回 Hash 对象中键的符号(默认值:字符串)。
Psych.load("---\n foo: bar") # => {"foo"=>"bar"} Psych.load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
当 `yaml` 参数为 NilClass 时,会引发 TypeError。此方法类似于 `safe_load`,只不过默认情况下允许使用 `Symbol` 对象。
源代码
# File ext/psych/lib/psych.rb, line 687 def self.load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| self.load f, filename: filename, **kwargs } end
加载 filename 中包含的文档。将 filename 中包含的 yaml 作为 Ruby 对象返回,如果文件为空,则返回指定的 fallback 返回值,默认为 nil。有关选项,请参阅 load。
源代码
# File ext/psych/lib/psych.rb, line 644 def self.load_stream yaml, filename: nil, fallback: [], **kwargs result = if block_given? parse_stream(yaml, filename: filename) do |node| yield node.to_ruby(**kwargs) end else parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) } end return fallback if result.is_a?(Array) && result.empty? result end
加载 yaml 中给出的多个文档。将解析的文档作为列表返回。如果给定了块,则每个文档将被转换为 Ruby 并在解析过程中传递给该块
示例
Psych.load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar'] list = [] Psych.load_stream("--- foo\n...\n--- bar\n...") do |ruby| list << ruby end list # => ['foo', 'bar']
源代码
# File ext/psych/lib/psych.rb, line 400 def self.parse yaml, filename: nil parse_stream(yaml, filename: filename) do |node| return node end false end
解析 yaml 中的 YAML 字符串。返回 Psych::Nodes::Document。如果引发 Psych::SyntaxError,则 filename 将用于异常消息中。
当检测到 YAML 语法错误时,会引发 Psych::SyntaxError。
示例
Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00> begin Psych.parse("--- `", filename: "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
有关 YAML AST 的更多信息,请参阅 Psych::Nodes。
源代码
# File ext/psych/lib/psych.rb, line 412 def self.parse_file filename, fallback: false result = File.open filename, 'r:bom|utf-8' do |f| parse f, filename: filename end result || fallback end
解析 filename 处的文件。返回 Psych::Nodes::Document。
当检测到 YAML 语法错误时,会引发 Psych::SyntaxError。
源代码
# File ext/psych/lib/psych.rb, line 454 def self.parse_stream yaml, filename: nil, &block if block_given? parser = Psych::Parser.new(Handlers::DocumentStream.new(&block)) parser.parse yaml, filename else parser = self.parser parser.parse yaml, filename parser.handler.root end end
解析 yaml 中的 YAML 字符串。返回 Psych::Nodes::Stream。此方法可以处理 yaml 中包含的多个 YAML 文档。如果引发 Psych::SyntaxError,则 filename 将用于异常消息中。
如果给定了块,则在解析时会将 Psych::Nodes::Document 节点传递给该块。
当检测到 YAML 语法错误时,会引发 Psych::SyntaxError。
示例
Psych.parse_stream("---\n - a\n - b") # => #<Psych::Nodes::Stream:0x00> Psych.parse_stream("--- a\n--- b") do |node| node # => #<Psych::Nodes::Document:0x00> end begin Psych.parse_stream("--- `", filename: "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
有关 YAML AST 的更多信息,请参阅 Psych::Nodes。
源代码
# File ext/psych/lib/psych.rb, line 421 def self.parser Psych::Parser.new(TreeBuilder.new) end
返回默认解析器
源代码
# File ext/psych/lib/psych.rb, line 596 def self.safe_dump o, io = nil, options = {} if Hash === io options = io io = nil end visitor = Psych::Visitors::RestrictedYAMLTree.create options visitor << o visitor.tree.yaml io, options end
安全地将 Ruby 对象 o 转储为 YAML 字符串。 可以传入可选的 options 来控制输出格式。 如果传入一个 IO 对象,YAML 将会被转储到该 IO 对象。 默认情况下,只允许序列化以下类
可以通过将类添加到 permitted_classes 关键字参数中来允许任意类。 它们是累加的。 例如,要允许 Date 序列化
Psych.safe_dump(yaml, permitted_classes: [Date])
现在,除了上面列出的类之外,Date 类也可以被转储。
如果对象包含不在 permitted_classes 列表中的类,则会引发 Psych::DisallowedClass 异常。
当前支持的选项有
:indentation-
用于缩进的空格字符数。可接受的值应在
0..9范围内,否则将忽略该选项。默认值:
2。 :line_width-
换行的最大字符数。对于无限行宽,请使用
-1。默认值:
0(表示“在 81 处换行”)。 :canonical-
写入“规范”
YAML形式(非常冗长,但严格正式)。默认值:
false。 :header-
在文档开头写入
%YAML [version]。默认值:
false。 :stringify_names-
将
Hash对象中的符号键转储为字符串。默认值:
false。
示例
# Dump an array, get back a YAML string Psych.safe_dump(['a', 'b']) # => "---\n- a\n- b\n" # Dump an array to an IO object Psych.safe_dump(['a', 'b'], StringIO.new) # => #<StringIO:0x000001009d0890> # Dump an array with indentation set Psych.safe_dump(['a', ['b']], indentation: 3) # => "---\n- a\n- - b\n" # Dump an array to an IO with indentation set Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3) # Dump hash with symbol keys as string Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n"
源代码
# File ext/psych/lib/psych.rb, line 324 def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false result = parse(yaml, filename: filename) return fallback unless result class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s), permitted_symbols.map(&:to_s)) scanner = ScalarScanner.new class_loader, strict_integer: strict_integer visitor = if aliases Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze else Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze end result = visitor.accept result result end
安全地加载 yaml 中的 yaml 字符串。 默认情况下,只允许反序列化以下类
默认情况下不允许递归数据结构。 可以通过将类添加到 permitted_classes 关键字参数中来允许任意类。 它们是累加的。 例如,要允许 Date 反序列化
Psych.safe_load(yaml, permitted_classes: [Date])
现在,除了上面列出的类之外,还可以加载 Date 类。
可以通过更改 aliases 关键字参数来显式允许别名。 例如
x = [] x << x yaml = Psych.dump x Psych.safe_load yaml # => raises an exception Psych.safe_load yaml, aliases: true # => loads the aliases
如果 yaml 包含不在 permitted_classes 列表中的类,则会引发 Psych::DisallowedClass 异常。
如果 yaml 包含别名,但 aliases 关键字参数设置为 false,则会引发 Psych::AliasesNotEnabled 异常。
如果在解析时引发任何异常,filename 将在异常消息中使用。
当可选的 symbolize_names 关键字参数设置为 true 值时,将返回 Hash 对象中键的符号(默认值:字符串)。
Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"} Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
源代码
# File ext/psych/lib/psych.rb, line 676 def self.safe_load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| self.safe_load f, filename: filename, **kwargs } end
安全地加载 filename 中包含的文档。 将 filename 中包含的 yaml 作为 Ruby 对象返回,如果文件为空,则返回指定的 fallback 返回值,默认为 nil。 有关选项,请参阅 safe_load。
源代码
# File ext/psych/lib/psych.rb, line 623 def self.to_json object visitor = Psych::Visitors::JSONTree.create visitor << object visitor.tree.yaml end
将 Ruby object 转储为 JSON 字符串。
源代码
# File ext/psych/lib/psych.rb, line 273 def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false result = parse(yaml, filename: filename) return fallback unless result result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer) end
将 yaml 加载到 Ruby 数据结构中。 如果提供了多个文档,将返回第一个文档中包含的对象。 如果在解析时引发任何异常,filename 将在异常消息中使用。 如果 yaml 为空,则返回指定的 fallback 返回值,默认为 false。
当检测到 YAML 语法错误时,会引发 Psych::SyntaxError。
示例
Psych.unsafe_load("--- a") # => 'a' Psych.unsafe_load("---\n - a\n - b") # => ['a', 'b'] begin Psych.unsafe_load("--- `", filename: "file.txt") rescue Psych::SyntaxError => ex ex.file # => 'file.txt' ex.message # => "(file.txt): found character that cannot start any token" end
当可选的 symbolize_names 关键字参数设置为 true 值时,将返回 Hash 对象中键的符号(默认值:字符串)。
Psych.unsafe_load("---\n foo: bar") # => {"foo"=>"bar"} Psych.unsafe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
当 'yaml' 参数为 NilClass 时,会引发 TypeError
注意:此方法*不应* 用于解析不受信任的文档,例如通过用户输入提供的 YAML 文档。 请改用 load 方法或 safe_load 方法。
源代码
# File ext/psych/lib/psych.rb, line 665 def self.unsafe_load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| self.unsafe_load f, filename: filename, **kwargs } end
加载 filename 中包含的文档。 将 filename 中包含的 yaml 作为 Ruby 对象返回,如果文件为空,则返回指定的 fallback 返回值,默认为 false。
注意:此方法*不应* 用于解析不受信任的文档,例如通过用户输入提供的 YAML 文档。 请改用 safe_load_file 方法。