2010-01-01 13 views
13

Me parece que la biblioteca YAML que se envía con ruby ​​1.9 está codificando-deaf.Ruby 1.9, YAML, y codificaciones de cuerdas: ¿cómo llevar una vida de cordura?

Lo que esto significa es que al generar YAML, tomará cualquier cadena de bytes y escapará cualquier secuencia de bytes que no genere ASCII limpio. Eso es cojo, pero aceptable.

Mi problema es al revés. Al cargar contenido de dicho volcado de YAML.

En el ejemplo que sigue creo una cadena UTF-8, volcarla, se vacía con el tipo !binary. Cuando lo vuelvo a cargar, tiene la codificación ASCII-8BIT. Al final del ejemplo, intento concatenar tanto la cadena original como la cadena recargada con otra cadena UTF-8. El último fallará con un 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 

creo que es claro cómo esto conducirá rápidamente a problemas cuando se trata con alguna fuente YAML que contiene hashes anidados y matrices con las cadenas de las hojas.

Actualmente tengo un código que atraviesa todos los hash y arreglos y llama a force_encoding en cada cadena. Eso, por decir lo menos, es antiestético.

Lo que estoy buscando en este momento es una manera de contar YAML::load que cualquier cadena que viene en debe ser tratado como, y por lo tanto tener su codificación UTF-8.


Idealmente, ruby's YAML solo debe anotar las cadenas que vuelca con la codificación adecuada. Hay un proyecto Ya2YAML que intenta volcar el YAML seguro UTF-8. No estoy seguro de qué tan avanzado está. Si alguien ha jugado con él, doy la bienvenida a cualquier idea.

Independientemente de eso, todavía tengo estos vertederos sin información de codificación para tratar. Aunque sé que son todos UTF-8.

+2

+1 para las diéresis de metal pesado. –

+0

Acabo de encontrarme con el mismo error/comportamiento ... ¿Has encontrado otra solución o sigues haciendo YAML.load y luego forzando codificación obligatoria ('utf-8') en cada cadena? – severin

Respuesta

1

En primer lugar, el archivo de texto que está intentando leer debe estar codificado en UTF-8 (este debe ser su archivo YAML).

A continuación, añadir esta línea a la parte superior de su archivo de rubí, hash y todo

# encoding: UTF-8 

Esto significa que la codificación predeterminada para todas las cadenas será UTF-8, y debería significar que cualquier texto que volcar con YAML.dump ('text') o incluso los literales de cadena 'como este' también deberían codificarse UTF-8, y todo debería funcionar bien a partir de ahora.

+0

No importa. Las cosas leídas como! Binary desde el yaml terminan como ASCII-8BIT, por razones quizás obvias y sensatas, pero así yaml debería volcar correctamente las cadenas UTF8 no guardadas. Tengo más o menos una solución para esto, pero implica un buen código de fragmento. Publicaré una respuesta cuando tenga una gema lista. – kch

3

Considere actualizar su ruby ​​a la última versión 1.9.2 .

Encontré ese error en 1.9.1 pero no en 1.9.2.

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

respuesta de Evgeny todavía muestra binaria para mí, pero esto funciona (instoad 'Syck' de 'psicología'):

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

estoy usando Ruby 1.9. Tenga en cuenta que para mi propósito que se escapen los especiales está bien, solo lo necesitaba para no mostrarlo ... binario ... para palabras normales. Gracias a Dios .to_yaml es funcional para mí otra vez, solía usarlo todo el tiempo. Cómo cargar una vida de cordura de hecho :)

+0

Gracias por esa corrección user1262147 - yamler = 'psych' no hizo nada por mí, pero yamler = 'syck' lo solucionó. Anteriormente, to_yaml había estado volcando todo como! Binary = whatever, incluso nombres de atributo de un ActiveRecord que provenía de una tabla UTF8 mysql. –

+0

La respuesta está desactualizada, no estaba actualizada cuando se creó, syck está obsoleta – bbozo

Cuestiones relacionadas