Кодирование::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 :)

Из документов:

Устанавливает заменяющую строку заданным объектом для неопределенного символа. Объект должен быть хешем, процедурой, методом или объектом, имеющим [] метод. Его ключ - неопределенный символ, закодированный в исходной кодировке текущего транскодера. Его значение может быть любой кодировкой, пока оно не будет преобразовано в целевую кодировку транскодера.

Другие вопросы по тегам