Кодирование::UndefinedConversionError
Я продолжаю получать Encoding::UndefinedConversionError - "\xC2" from ASCII-8BIT to UTF-8
каждый раз, когда я пытаюсь преобразовать хэш в строку JSON. Я пробовал с [.encode | .force_encoding](["UTF-8" | "ASCII-8BIT" ])
, цепочка .encode
с .force_encoding
в обратном направлении переключение параметров, но, похоже, ничего не работает, поэтому я уловил такую ошибку
begin
menu.to_json
rescue Encoding::UndefinedConversionError
puts $!.error_char.dump
p $!.error_char.encoding
end
Где menu - это продолжение dataset.to_hash с содержимым из базы данных MySQL, кодировка utf8_general_ci и возвращаемое так:
"\ Xc2"
<#Encoding: ASCII-8BIT>
Кодировка никогда не меняется, несмотря ни на что .encode
/.force_encoding
Я использую. Я даже пытался заменить строку .gsub!(/\\\xC2/)
без удачи
Есть идеи?
4 ответа
menu.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
Это сработало отлично, мне пришлось заменить некоторые дополнительные символы, но больше ошибок нет.
Что вы ожидаете от "\xC2"? Вероятно, Â
С ASCII-8BIT у вас есть двоичные данные, и рубин не может решить, что должно быть.
Сначала вы должны установить кодировку с force_encoding
,
Вы можете попробовать следующий код:
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"
}
Результатом являются возможные значения в разных кодировках для вашего "\xC2".
Результат может зависеть от вашего формата вывода, но я думаю, вы можете сделать правильное предположение, какая у вас кодировка.
Когда вы определили нужную вам кодировку (вероятно, cp1251), вы можете
menu.force_encoding('cp1252').to_json
Смотрите также комментарий Kashyaps.
Если вы не заботитесь о потере странных персонажей, вы можете выбросить их:
str.force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')
Ваше автоматически принятое решение не работает, в нем практически нет ошибок, но это НЕ JSON.
Я решил проблему с помощью OJ Gem, теперь он работает найти. Это также быстрее, чем стандартная библиотека JSON.
Написание:
menu_json = Oj.dump menu
Чтение:
menu2 = Oj.load menu_json
https://github.com/ohler55/oj для более подробной информации. Надеюсь, это поможет.
Параметр:fallback может быть полезен, если вы знаете, какие символы хотите заменить
"Text ".encode("ASCII", "UTF-8", fallback: {"" => ":)"})
#=> hello :)
Из документов:
Устанавливает заменяющую строку заданным объектом для неопределенного символа. Объект должен быть хешем, процедурой, методом или объектом, имеющим [] метод. Его ключ - неопределенный символ, закодированный в исходной кодировке текущего транскодера. Его значение может быть любой кодировкой, пока оно не будет преобразовано в целевую кодировку транскодера.