Ruby'to_json'抛出ArgumentError:UTF-8中无效的字节序列

时间:2018-10-30 12:56:09

标签: ruby-on-rails json ruby encoding

在Rails控制台中,我得到:

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 :(得分:2)

这是因为您的输入String包含 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控制台中显示。

答案 1 :(得分:0)

如果您不怕丢失内容,可以使用以下解决方案:

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

=> "{\"name\":\"     \"}"

答案 2 :(得分:0)

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":"სსიპ ოთარ ჩხეიძის სახელობის სოფელ ყე"}

答案 3 :(得分:0)

谢谢Stefan,Masa Sakano和Alexey Strizhak。您的建议对我有很大帮助。 字符串具有无效的字节序列字符是正确的。 我所做的只是保持如下所示的有效编码字符-

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

这将删除不完整/无效的字符,例如“ \ xE1 \ x83”。

再次感谢大家帮助我了解问题并提出解决方案。