модуль Psych
Обзор
Psych — это парсер и генератор YAML. Psych использует libyaml [Главная страница: pyyaml.org/wiki/LibYAML] или [Репозиторий HG: bitbucket.org/xi/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, а на самом высоком уровне — возможность распаковки YAML в объекты Ruby.
Генерация YAML
Psych предоставляет различные интерфейсы, от низкого до высокого уровня, для создания документов YAML. Очень похоже на интерфейсы парсинга YAML, Psych предоставляет на самом низком уровне систему на основе событий, на среднем уровне — построение дерева абстрактного синтаксиса YAML, а на самом высоком уровне — преобразование объекта Ruby непосредственно в документ YAML.
API высокого уровня
Парсинг
Парсер YAML высокого уровня, предоставляемый Psych, просто принимает YAML в качестве входных данных и возвращает структуру данных Ruby. Для получения информации об использовании парсера высокого уровня см. ::load
Чтение из строки
Psych.load("--- a") # => 'a'
Psych.load("---\n - a\n - b") # => ['a', 'b']
Чтение из файла
Psych.load_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
Генерация
Интерфейс генератора высокого уровня самый простой. Psych просто принимает структуру данных Ruby и преобразует ее в документ YAML. Более подробную информацию о выводе структуры данных Ruby см. в ::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 предоставляет доступ к дереву абстрактного синтаксиса (AST), полученному в результате парсинга документа YAML. Это дерево строится с помощью Psych::Parser и Psych::TreeBuilder. Дерево AST можно свободно исследовать и изменять. Для получения дополнительной информации о работе с деревьями синтаксиса YAML см. ::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 точно такое же, как AST, используемое при парсинге документа YAML. Пользователи могут вручную построить AST, и AST знает, как сгенерировать себя в виде документа YAML. Для получения дополнительной информации о создании дерева абстрактного синтаксиса YAML см. 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.
Чтение в структуру
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 433
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.
Пример:
# 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)
# File ext/psych/lib/psych.rb, line 450
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((long)major);
list[1] = INT2NUM((long)minor);
list[2] = INT2NUM((long)patch);
return rb_ary_new4((long)3, list);
} Возвращает версию используемого libyaml.
# File ext/psych/lib/psych.rb, line 261 def self.load yaml, filename = nil, fallback: false, symbolize_names: false result = parse(yaml, filename, fallback: fallback) result = result.to_ruby if result symbolize_names!(result) if symbolize_names result end
Загружает yaml в структуру данных Ruby. Если предоставлено несколько документов, будет возвращен объект, содержащийся в первом документе. filename будет использоваться в сообщении об ошибке, если при парсинге возникнет какая-либо ошибка.
Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.
Пример:
Psych.load("--- a") # => 'a'
Psych.load("---\n - a\n - b") # => ['a', 'b']
begin
Psych.load("--- `", "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"}
# File ext/psych/lib/psych.rb, line 495
def self.load_file filename, fallback: false
File.open(filename, 'r:bom|utf-8') { |f|
self.load f, filename, fallback: FALLBACK.new(fallback)
}
end Загружает документ, содержащийся в filename. Возвращает YAML, содержащийся в filename, как объект Ruby, или, если файл пуст, возвращает заданное значение по умолчанию, которое по умолчанию — пустой Hash.
# File ext/psych/lib/psych.rb, line 481
def self.load_stream yaml, filename = nil
if block_given?
parse_stream(yaml, filename) do |node|
yield node.to_ruby
end
else
parse_stream(yaml, filename).children.map { |child| child.to_ruby }
end
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 348
def self.parse yaml, filename = nil, fallback: false
parse_stream(yaml, filename) do |node|
return node
end
fallback
end Разбирает строку YAML в yaml. Возвращает Psych::Nodes::Document. filename используется в сообщении об ошибке, если возникает Psych::SyntaxError.
Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.
Пример:
Psych.parse("---\n - a\n - b") # => #<Psych::Nodes::Document:0x00>
begin
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::Nodes для получения дополнительной информации об абстрактном синтаксическом дереве YAML.
# File ext/psych/lib/psych.rb, line 359
def self.parse_file filename
File.open filename, 'r:bom|utf-8' do |f|
parse f, filename
end
end Разбирает файл по адресу filename. Возвращает Psych::Nodes::Document.
Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.
# File ext/psych/lib/psych.rb, line 398
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. filename используется в сообщении об ошибке, если возникает Psych::SyntaxError.
Если указан блок, узел Psych::Nodes::Document будет передан в блок по мере его разбора.
Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.
Пример:
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("--- `", "file.txt")
rescue Psych::SyntaxError => ex
ex.file # => 'file.txt'
ex.message # => "(file.txt): found character that cannot start any token"
end
См. Psych::Nodes для получения дополнительной информации об абстрактном синтаксическом дереве YAML.
# File ext/psych/lib/psych.rb, line 367 def self.parser Psych::Parser.new(TreeBuilder.new) end
Возвращает парсер по умолчанию.
# File ext/psych/lib/psych.rb, line 312
def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil, symbolize_names: false
result = parse(yaml, filename)
return unless result
class_loader = ClassLoader::Restricted.new(whitelist_classes.map(&:to_s),
whitelist_symbols.map(&:to_s))
scanner = ScalarScanner.new class_loader
if aliases
visitor = Visitors::ToRuby.new scanner, class_loader
else
visitor = Visitors::NoAliasRuby.new scanner, class_loader
end
result = visitor.accept result
symbolize_names!(result) if symbolize_names
result
end Безопасно загружает строку yaml в yaml. По умолчанию разрешается десериализация только следующих классов:
-
String
-
Array
Вложенные структуры данных по умолчанию не допускаются. Произвольные классы могут быть разрешены, добавив эти классы в whitelist. Они добавляются. Например, чтобы разрешить десериализацию Date:
Psych.safe_load(yaml, [Date])
Теперь класс Date может быть загружен в дополнение к перечисленным выше классам.
Псевдонимы можно явно разрешить, изменив параметр aliases. Например:
x = [] x << x yaml = Psych.dump x Psych.safe_load yaml # => raises an exception Psych.safe_load yaml, [], [], true # => loads the aliases
Исключение Psych::DisallowedClass будет выброшено, если yaml содержит класс, который не указан в списке разрешенных.
Исключение Psych::BadAlias будет выброшено, если yaml содержит псевдонимы, но параметр aliases установлен в значение false.
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 460 def self.to_json object visitor = Psych::Visitors::JSONTree.create visitor << object visitor.tree.yaml end
Выводит объект Ruby object в строку JSON.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.