web-dev-qa-db-fra.com

Encoding :: UndefinedConversionError

Je reçois un Encoding::UndefinedConversionError - "\xC2" from ASCII-8BIT to UTF-8 Chaque fois que j'essaie de convertir un hachage en une chaîne JSON. J'ai essayé avec [.encode | .force_encoding](["UTF-8" | "ASCII-8BIT" ]), enchaînant .encode Avec .force_encoding, En arrière, en changeant les paramètres mais rien ne semblait fonctionner alors j'ai attrapé l'erreur comme ceci:

begin
  menu.to_json
rescue Encoding::UndefinedConversionError
  puts $!.error_char.dump
  p $!.error_char.encoding
end

Où menu est le dataset.to_hash d'une suite avec le contenu d'une base de données MySQL, l'encodage utf8_general_ci et a renvoyé ceci:

"\ xC2"

<#Encoding: ASCII-8BIT>

L'encodage ne change jamais, peu importe ce que .encode/.force_encoding J'utilise. J'ai même essayé de remplacer la chaîne .gsub!(/\\\xC2/) sans chance.

Des idées?

34
martriay
menu.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')

Cela a fonctionné parfaitement, j'ai dû remplacer quelques caractères supplémentaires mais il n'y a plus d'erreurs.

75
martriay

Qu'attendez-vous pour "\ xC2"? Probablement un Â

Avec ASCII-8BIT, vous avez des données binaires et Ruby ne peux pas décider ce qui devrait être.

Vous devez d'abord définir l'encodage avec force_encoding.

Vous pouvez essayer le code suivant:

Encoding.list.each{|enc|
  begin
    print "%-10s\t" % [enc]
    print "\t\xC2".force_encoding(enc)
    print "\t\xC2".force_encoding(enc).encode('utf-8')
  rescue => err
    print "\t#{err}"
  end
  print "\n"
}

Le résultat est les valeurs possibles dans différents encodages pour votre "\ xC2".

Le résultat peut dépendre de votre format de sortie, mais je pense que vous pouvez faire une bonne supposition, quel encodage vous avez.

Lorsque vous avez défini l'encodage dont vous avez besoin (probablement cp1251), vous pouvez

menu.force_encoding('cp1252').to_json

Voir aussi le commentaire de Kashyaps.

18
knut

Si vous ne vous souciez pas de perdre les personnages étranges, vous pouvez les emporter:

str.force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')
11
Ponny

Votre solution acceptée automatiquement ne fonctionne pas, il n'y a effectivement aucune erreur, mais ce n'est PAS JSON.

J'ai résolu le problème en utilisant la gem oj, cela fonctionne maintenant trouver. Elle est également plus rapide que la bibliothèque JSON standard.

Écriture:

   menu_json = Oj.dump menu

En train de lire :

   menu2 = Oj.load menu_json

https://github.com/ohler55/oj pour plus de détails. J'espère que cela aidera.

8
gvo