Ruby 'to_json' выдает ArgumentError: недопустимая последовательность байтов в UTF-8 - PullRequest
0 голосов
/ 30 октября 2018

В рельсах консоли я получаю:

hash = {"name"=>"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე\xE1\x83"}
#=> {"name"=>"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე\xE1\x83"}
hash.to_json
#>> ArgumentError: invalid byte sequence in UTF-8
from /home/edmodo/.rvm/gems/ruby-2.3.0@one-eye/gems/activesupport-json_encoder-1.1.0/lib/active_support/json/encoding/active_support_encoder.rb:79:in `gsub'

"\xE1\x83".to_json не работает, возможно, из-за символов, отличных от UTF-8.

Любая помощь приветствуется.

Если хеш-код преобразуется в строку, он работает, но добавляет символы мусора, такие как u003E, с большим количеством дополнительных обратных косых черт.

hash.to_s.to_json
#=> "\"{\\\"name\\\"=\\u003E\\\"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე\\\\xE1\\\\x83\\\"}\""

Ответы [ 4 ]

0 голосов
/ 01 ноября 2018

Спасибо Стефан, Маса Сакано и Алексей Стрижак. Ваши предложения мне очень помогли. Это верно, что строка содержит недопустимые символы последовательности байтов. То, что я сделал, это просто сохранил действительные символы кодирования, как показано ниже -

"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე\xE1\x83".chars.select(&:valid_encoding?).join
=> "სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე"

Это удалит неполные / недействительные символы, такие как "\ xE1 \ x83".

Еще раз большое спасибо всем за помощь в понимании проблемы и предложении решений.

0 голосов
/ 30 октября 2018

Если вы не боитесь потерять контент, можете воспользоваться этим решением:

pry(main)> 
{"name"=>"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე\xE1\x83".force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')}.to_json

=> "{\"name\":\"     \"}"
0 голосов
/ 31 октября 2018
require 'json'

def cleanup(string)
  text = ''
  string.each_char { |char| text << char if char.valid_encoding? }
  text
end

hash = { "name" => "სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე\xE1\x83" }
hash.transform_values! { |value| cleanup(value) }

puts hash.to_json

{"name":"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე"}
0 голосов
/ 30 октября 2018

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

hash['name'].valid_encoding?  # => false

По сути, вы должны исправить входную строку, удалив все недопустимые байтовые последовательности символов; в вашем примере это "\xE1\x83"

Если по какой-то причине вам необходимо сохранить последовательность байтов и кодировать ее в стандартный JSON, я думаю, что вы должны сначала кодировать строку, поскольку JSON не принимает двоичные данные, а только допустимые строки UTF-8. Обратите внимание, что строка с недопустимой байтовой последовательностью - это двоичные данные для JSON.

В Rails вы можете использовать кодировку Base64 следующим образом:

hash['name'] = Base64.encode64 hash['name']
hash.to_json  # => a valid JSON

При декодировании необходимо указать кодировку, например,

hj = hash.to_json
Base64.decode64(JSON.parse(hj)['name']).force_encoding('UTF-8') # => Decoded string

Обратите внимание, что воспроизводимая строка НЕ в любом случае является действительным UTF-8 в вашем случае. Но это помогло бы отобразить в консоли Rails.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...