Spec-Zone.ru › Ruby 3.4

модуль 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

Парсинг

Высокоуровневый парсер YAML, предоставляемый Psych, просто принимает 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 предоставляет доступ к AST, созданной при парсинге документа YAML. Это дерево построено с использованием 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 точно такая же, как и AST, используемая при парсинге документа YAML. Пользователи могут вручную построить 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.

Чтение в структуру

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"

Константы

DEFAULT_SNAKEYAML_VERSION
LIBYAML_VERSION

Версия libyaml, используемая Psych

VERSION

Версия Psych, которую вы используете

Методы публичного класса

dump(o) → строка yaml
dump(o, options) → строка yaml
dump(o, io) → переданный объект io
dump(o, io, options) → переданный объект io
Исходный код
# 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"
dump_stream (*objects)
Исходный код
# 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"
libyaml_version
Исходный код
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

load (yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false)
Исходный код
# 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.

Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.

Пример:

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"}

Вызывает TypeError, когда параметр ‘yaml` имеет значение NilClass. Этот метод аналогичен `safe_load`, за исключением того, что объекты `Symbol` разрешены по умолчанию.

load_file (filename, **kwargs)
Исходный код
# 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. Возвращает yaml, содержащийся в filename, как объект Ruby, или если файл пуст, возвращает указанное значение fallback, которое по умолчанию равно nil. См. load для параметров.

load_stream (yaml, filename: nil, fallback: [], **kwargs) { |to_ruby(**kwargs)| ... }
Исходный код
# 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']
parse (yaml, filename: nil)
Исходный код
# 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. filename используется в сообщении об ошибке, если возникает исключение Psych::SyntaxError.

Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.

Пример:

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

См. Psych::Nodes для получения дополнительной информации об YAML AST.

parse_file (filename, fallback: false)
Исходный код
# 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.

Вызывает исключение Psych::SyntaxError, когда обнаружена ошибка синтаксиса YAML.

parse_stream (yaml, filename: nil, &block)
Исходный код
# 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. 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("--- `", filename: "file.txt")
rescue Psych::SyntaxError => ex
  ex.file    # => 'file.txt'
  ex.message # => "(file.txt): found character that cannot start any token"
end

Вызывает TypeError, когда передан NilClass.

См. Psych::Nodes для получения дополнительной информации об YAML AST.

parser ()
Исходный код
# File ext/psych/lib/psych.rb, line 421
def self.parser
  Psych::Parser.new(TreeBuilder.new)
end

Возвращает стандартный парсер

END_OF_DOCUMENT_MARKER
safe_dump(o) → строка yaml
safe_dump(o, options) → строка yaml
safe_dump(o, io) → объект io
safe_dump(o, io, options) → объект io
Исходный код
# 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. По умолчанию разрешены только следующие классы:

  • TrueClass

  • FalseClass

  • NilClass

  • Integer

  • Float

  • String

  • Array

  • Hash

Произвольные классы могут быть разрешены путем добавления этих классов в аргумент permitted_classes. Они добавляются. Например, для разрешения сериализации Date:

Psych.safe_dump(yaml, permitted_classes: [Date])

Теперь класс Date может быть выведен помимо перечисленных выше классов.

Исключение Psych::DisallowedClass будет поднято, если объект содержит класс, который не находится в списке permitted_classes.

В настоящее время поддерживаются следующие параметры:

: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"
safe_load (yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false)
Исходный код
# 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. По умолчанию разрешены только следующие классы:

  • TrueClass

  • FalseClass

  • NilClass

  • Integer

  • Float

  • String

  • Array

  • Hash

Рекурсивные структуры данных по умолчанию не разрешены. Произвольные классы могут быть разрешены путем добавления этих классов в аргумент 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

Исключение Psych::DisallowedClass будет поднято, если yaml содержит класс, который не находится в списке permitted_classes.

Исключение Psych::AliasesNotEnabled будет поднято, если 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"}
safe_load_file (filename, **kwargs)
Исходный код
# 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. Возвращает yaml, содержащийся в filename, как объект Ruby, или если файл пуст, то возвращает указанное fallback значение возврата, по умолчанию nil. См. safe_load для параметров.

to_json (object)
Исходный код
# 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.

unsafe_load (yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false)
Исходный код
# 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.

Вызывает исключение Psych::SyntaxError при обнаружении синтаксической ошибки YAML.

Пример:

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"}

Вызывает исключение TypeError, если параметр ‘yaml` равен NilClass

ПРИМЕЧАНИЕ: Этот метод *не следует* использовать для парсинга недоверенных документов, таких как YAML документы, предоставленные пользователем. Вместо этого используйте метод load или метод safe_load.

unsafe_load_file (filename, **kwargs)
Исходный код
# 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. Возвращает yaml, содержащийся в filename, как объект Ruby, или если файл пуст, то возвращает указанное fallback значение возврата, по умолчанию false.

ПРИМЕЧАНИЕ: Этот метод *не следует* использовать для парсинга недоверенных документов, таких как YAML документы, предоставленные пользователем. Вместо этого используйте метод safe_load_file.

Ruby Core © 1993–2024 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API