16

JSON::GeneratorError: source sequence is illegal/malformed utf-8ハッシュを json 文字列に変換しようとしたときにエラーが発生しました。これがエンコーディングと関係があるのか​​ 、どうすれば to_json が \xAE をそのまま扱うようにできますか?

$ irb
2.0.0-p247 :001 > require 'json'
=> true
2.0.0-p247 :002 > a = {"description"=> "iPhone\xAE"}
=> {"description"=>"iPhone\xAE"}
2.0.0-p247 :003 > a.to_json
JSON::GeneratorError: source sequence is illegal/malformed utf-8
  from (irb):3:in `to_json'
  from (irb):3
  from /Users/cchen21/.rvm/rubies/ruby-2.0.0-p247/bin/irb:16:in `<main>'
4

2 に答える 2

24

\xAEは UTF-8 では有効な文字ではありません。\u00AE代わりに次を使用する必要があります。

"iPhone\u00AE"
#=> "iPhone®"

または、それに応じて変換します。

"iPhone\xAE".force_encoding("ISO-8859-1").encode("UTF-8")
#=> "iPhone®"
于 2013-08-05T21:00:12.897 に答える
20

Ruby のすべての文字列には、基になるエンコーディングがあります。環境変数によってはLANG、インタラクティブ シェルが特定のエンコーディングで文字列を実行および解釈している可能性があります。LC_ALL

$ irb
1.9.3p392 :008 > __ENCODING__
 => #<Encoding:UTF-8>

(Ruby 2.0 ではなく 1.9 を使用していることは無視してください。考え方は同じです)。

__ENCODING__現在のソース エンコーディングを返します。あなたはおそらくUTF-8とも言うでしょう。

コードでリテラル文字列を作成し、バイト エスケープ ( \xAE) を使用すると、Ruby は文字列エンコーディングに従ってそれを解釈しようとします。

1.9.3p392 :003 > a = {"description" => "iPhone\xAE"}
 => {"description"=>"iPhone\xAE"}
1.9.3p392 :004 > a["description"].encoding
 => #<Encoding:UTF-8>

そのため、リテラル文字列の最後のバイト\xAEは UTF-8 ストリーム バイトとして扱われるように試みられますが、無効です。印刷しようとするとどうなるか見てみましょう:

1.9.3-p392 :001 > puts "iPhone\xAE"
iPhone�
 => nil

登録されたマーク文字を有効な UTF-8 エンコーディングで提供する必要があります (実際の文字を使用するか、2 つの UTF-8 バイトを提供します)。

1.9.3-p392 :002 > a = {"description1" => "iPhone®", "description2" => "iPhone\xc2\xae"}
 => {"description1"=>"iPhone®", "description2"=>"iPhone®"}
1.9.3-p392 :005 > a.to_json
 => "{\"description1\":\"iPhone®\",\"description2\":\"iPhone®\"}"

または、入力が ISO-8859-1 (Latin 1) であり、それが確実にわかっている場合は、文字列を別のエンコーディングとして解釈するよう Ruby に指示できます。

1.9.3-p392 :006 > a = {"description1" => "iPhone\xAE".force_encoding('ISO-8859-1') }
 => {"description1"=>"iPhone\xAE"}
1.9.3-p392 :007 > a.to_json
 => "{\"description1\":\"iPhone®\"}"

それが役に立てば幸い。

于 2013-08-05T21:02:19.857 に答える