Spec-Zone.ru › Ruby 2.4

модуль 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, от низкого до высокого уровня, в зависимости от ваших потребностей в парсинге. На самом низком уровне — это парсер на основе событий. На среднем уровне — доступ к исходному AST YAML, а на самом высоком уровне — возможность распаковки YAML в объекты Ruby.

Генерация YAML

Psych предоставляет ряд интерфейсов для создания документов YAML, начиная от низкого и до высокого уровня. Очень похожие на интерфейсы парсинга YAML, Psych предоставляет на самом низком уровне систему на основе событий, на среднем уровне — построение AST 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. См. ::dump для получения дополнительной информации о выгрузке структуры данных Ruby.

Запись в строку

# 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. Для получения дополнительной информации о построении AST 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>

Получение потока событий

parser = Psych::Parser.new(Psych::Handlers::Recorder.new)

parser.parse("---\n - a\n - b")
parser.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, которую вы используете

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

add_private_type(type_tag, &block) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 49
def self.add_private_type type_tag, &block
  warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE
  domain = 'x-private'
  key = [domain, type_tag].join ':'
  @domain_types[key] = [key, block]
end
add_ruby_type(type_tag, &block) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 42
def self.add_ruby_type type_tag, &block
  warn "#{caller[0]}: add_ruby_type is deprecated, use add_domain_type" if $VERBOSE
  domain = 'ruby.yaml.org,2002'
  key = ['tag', domain, type_tag].join ':'
  @domain_types[key] = [key, block]
end
detect_implicit(thing) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 34
def self.detect_implicit thing
  warn "#{caller[0]}: detect_implicit is deprecated" if $VERBOSE
  return '' unless String === thing
  return 'null' if '' == thing
  ss = ScalarScanner.new(ClassLoader.new)
  ss.tokenize(thing).class.name.downcase
end
dump(o) → строка yaml Показать исходный код
dump(o, options) → строка yaml
dump(o, io) → объект io
dump(o, io, options) → объект io
# File ext/psych/lib/psych.rb, line 408
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)
dump_stream(*objects) Показать исходный код
# File ext/psych/lib/psych.rb, line 425
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((long)major);
    list[1] = INT2NUM((long)minor);
    list[2] = INT2NUM((long)patch);

    return rb_ary_new4((long)3, list);
}

Возвращает версию используемого libyaml

load(yaml, filename = nil, fallback = false) Показать исходный код
# File ext/psych/lib/psych.rb, line 250
def self.load yaml, filename = nil, fallback = false
  result = parse(yaml, filename, fallback)
  result ? result.to_ruby : 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
load_documents(yaml, &block) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 25
def self.load_documents yaml, &block
  if $VERBOSE
    warn "#{caller[0]}: load_documents is deprecated, use load_stream"
  end
  list = load_stream yaml
  return list unless block_given?
  list.each(&block)
end

Этот метод устарел, используйте ::load_stream вместо него.

load_file(filename, fallback = false) Показать исходный код
# File ext/psych/lib/psych.rb, line 470
def self.load_file filename, fallback = false
  File.open(filename, 'r:bom|utf-8') { |f|
    self.load f, filename, FALLBACK.new(fallback)
  }
end

Загрузить документ, содержащийся в filename. Возвращает yaml, содержащийся в filename в виде объекта Ruby, или, если файл пустой, возвращает указанное значение по умолчанию, по умолчанию — пустой Хэш

load_stream(yaml, filename = nil) { |to_ruby| ... } Показать исходный код
# File ext/psych/lib/psych.rb, line 456
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']
object_maker(klass, hash) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 72
def self.object_maker klass, hash
  warn "#{caller[0]}: object_maker is deprecated" if $VERBOSE
  klass.allocate.tap do |obj|
    hash.each { |k,v| obj.instance_variable_set(:"@#{k}", v) }
  end
end
parse(yaml, filename = nil, fallback = false) Показать исходный код
# File ext/psych/lib/psych.rb, line 323
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.

parse_file(filename) Показать исходный код
# File ext/psych/lib/psych.rb, line 334
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.

parse_stream(yaml, filename = nil, &block) Показать исходный код
# File ext/psych/lib/psych.rb, line 373
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.

parser() Показать исходный код
# File ext/psych/lib/psych.rb, line 342
def self.parser
  Psych::Parser.new(TreeBuilder.new)
end

Возвращает парсер по умолчанию

read_type_class(type, reference) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 62
def self.read_type_class type, reference
  warn "#{caller[0]}: read_type_class is deprecated" if $VERBOSE
  _, _, type, name = type.split ':', 4

  reference = name.split('::').inject(reference) do |k,n|
    k.const_get(n.to_sym)
  end if name
  [type, reference]
end
safe_load(yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil) Показать исходный код
# File ext/psych/lib/psych.rb, line 289
def self.safe_load yaml, whitelist_classes = [], whitelist_symbols = [], aliases = false, filename = nil
  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
  visitor.accept result
end

Безопасно загрузить строку yaml в yaml. По умолчанию разрешается десериализация только следующих классов:

  • TrueClass

  • FalseClass

  • NilClass

  • Numeric

  • String

  • Array

  • Hash

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

tagurize(thing) Показать исходный код
# File ext/psych/lib/psych/deprecated.rb, line 56
def self.tagurize thing
  warn "#{caller[0]}: add_private_type is deprecated, use add_domain_type" if $VERBOSE
  return thing unless String === thing
  "tag:yaml.org,2002:#{thing}"
end
to_json(object) Показать исходный код
# File ext/psych/lib/psych.rb, line 435
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.

Spec-Zone.ru

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