Ruby 1.9, YAML и строковые кодировки: как вести жизнь здравомыслия?

Мне кажется, что библиотека YAML, которая поставляется с ruby ​​1.9, является кодирующей-глухой.

Это означает, что при создании YAML он берет любую строку байтов и избегает любой последовательности байтов, которая не выводит чистый ASCII. Это хромает, но приемлемо.

Моя проблема в другом. При загрузке содержимого из дампа YAML.

В следующем примере я создаю строку UTF-8, выгружаю ее, она сбрасывается с типом !binary. Когда я загружаю его, он имеет кодировку ASCII-8BIT. В конце примера я пытаюсь объединить как исходную, так и перезагруженную строку с другой строкой UTF-8. Последний будет терпеть неудачу с Encoding::CompatibilityError.

require 'yaml'
s0 = "Iñtërnâtiônàlizætiøn"
y  = s0.to_yaml
s1 = YAML::load y
puts s0                 # => Iñtërnâtiônàlizætiøn
puts s0.encoding        # => UTF-8
puts s1                 # => Iñtërnâtiônàlizætiøn
puts s1.encoding        # => ASCII-8BIT
puts y                  # => --- !binary |
                        #    ScOxdMOrcm7DonRpw7Ruw6BsaXrDpnRpw7hu
puts "ñårƒ" + s0        # => ñårƒIñtërnâtiônàlizætiøn
puts "ñårƒ" + s1        # => Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT

Я думаю, что это ясно, как это быстро приведет к неприятностям, когда вы имеете дело с каким-то источником YAML, содержащим вложенные хэши и массивы с листовыми строками.

В настоящее время у меня есть код, который пересекает все хэши и массивы и вызывает force_encoding для каждой строки. Это, мягко говоря, неприглядно.

То, что я ищу прямо сейчас, - это способ сообщить YAML::load, что любая строка, которая входит, должна рассматриваться как, и, следовательно, ее кодировка установлена ​​в UTF-8.


В идеале, ruby ​​YAML должен просто комментировать строки, которые он сбрасывает, с надлежащей кодировкой. Там проект Ya2YAML, который пытается сбросить безопасный YAML UTF-8. Я не уверен, насколько это далеко. Если кто-то играл с ним, я приветствую любые мысли.

Независимо от этого, у меня все еще есть эти дампы без какой-либо информации о кодировании. Хотя я знаю, что все они UTF-8.

Ответы

Ответ 1

Подумайте о том, чтобы обновить рубин до последней версии 1.9.2.

Я нашел ошибку в 1.9.1, но не 1.9.2.

Ответ 2

YAML::ENGINE.yamler='psych'
'Résumé'.to_yaml # => "--- Résumé\n...\n"

Ответ 3

Во-первых, текстовый файл, который вы пытаетесь прочитать, должен кодироваться в кодировке UTF-8 (это должен быть ваш файл YAML).

Затем добавьте эту строку в верхнюю часть вашего рубинового файла, хэш и все

# encoding: UTF-8

Это будет означать, что кодировка по умолчанию для всех строк будет UTF-8 и должна означать, что любой текст, который вы дампируете с помощью YAML.dump( "текст" ) или даже строковые литералы "как это", также должен быть закодирован UTF- 8, и все должно хорошо работать здесь.

Ответ 4

Евгений ответ все еще показывает двоичный код для меня, но это работает ( "syck" instoad "psych" ):

YAML::ENGINE.yamler='syck'
'Résumé'.to_yaml # => "--- "R\xE9sum\xE9"

Я использую Ruby 1.9. Заметьте, что для моих целей, у которых есть специальные экраны, все в порядке - мне просто нужно было не показывать! Binary... для обычных слов. Слава богу .to_yaml снова работает для меня - привык использовать его все время. Как правильно надеть жизнь здравого смысла:)