多くのオプションがあり、Python のバージョンに依存し、正しいコードを書くために絶対に完全に理解する必要があるかなり複雑なものに出くわしました。一般に、3.x で採用されたアプローチはより厳密で、作業が少し難しくなりますが、間違いを犯したり、複雑な状況に陥ったりする可能性ははるかに低くなります。(報告された正確な症状に基づいて、2.x を使用しているようです。)
json.dumps
2.x と 3.x では動作が異なります。2.x では、str
バイト文字列 (不明なエンコーディング) である が生成されます。3.x でも が生成されstr
ますがstr
、3.x では適切な Unicode 文字列になります。
JSON は本質的に Unicode をサポートする形式ですが、ファイルが UTF-8 エンコーディングであることを想定しています。ただし、JSON は文字列のスタイル エスケープをサポートしている\u
ことを理解しておいてください。このデータを読み取ると、正しいエンコードされた文字列が返されます。読み取りコードは、JSON から文字列を読み取るときに (2.x または 3.x のどちらを使用しても) Unicode オブジェクトを生成します。
ファイルを開くと、たとえば、「Damián」は「Dami\u00e1n」のように見えます。
á
ASCII で表すことはできません。\u00e1
他の問題を回避するために、デフォルトでエンコードされます。これは 3.x でも発生します。
ensure_ascii=偽
これにより、以前のエンコーディングが無効になります。2.x では、代わりにオブジェクトを取得することを意味します。つまり、元の文字unicode
を保持した実際の Unicode オブジェクトです。á
3.x では、文字が明示的に変換されていないことを意味します。しかし、いずれにせよ、それは Unicode string を与えることをensure_ascii=False
意味します。json.dumps
Unicode 文字列をファイルに書き込むには、エンコードする必要があります。「Unicode データ」などというものはありません。Unicode は抽象化です。2.x では、'ascii'
Unicode オブジェクトを にフィードすると、このエンコーディングは暗黙的に行われますfile.write
。を期待していましたstr
。これを回避するには、モジュールを使用するか、書く前にcodecs
明示的にエンコードします。'utf-8'
3.x では、ファイルのエンコードencoding
時にキーワード引数を使用してエンコードが設定されopen
ます (デフォルトはおそらく希望どおりではありません)。
エンコード (encoding='latin-1')
ここでは、辞書を作成する前にエンコードしているため、str
データにオブジェクトが含まれています。str
データにオブジェクトがある場合、JSON エンコーダーはデフォルトで、それらが UTF-8 エンコーディングのUnicode 文字列を表していると想定するため、問題が発生します。これは、2.x ではencoding
キーワード引数 toを使用して変更できますjson.dumps
。bytes
(3.x では、エンコーダーはオブジェクト、つまり非 Unicode 文字列のシリアル化を単純に拒否します!)
ただし、単にデータをファイルに直接取得することが目標である場合、これjson.dumps
は不適切なツールです。s
その名前が何のためにあるのか疑問に思ったことはありますか?「文字列」の略です。これは特殊なケースです。実際、通常のケースは、ファイルに直接書き込むことです! (文字列を与えて自分で書くことを期待する代わりに。) これがjson.dump
(no 's') の機能です。繰り返しになりますが、JSON 標準は UTF-8 エンコーディングを想定しており、2.x にはencoding
デフォルトで UTF-8 に設定されるキーワード パラメータがあります (これはそのままにしておく必要があります)。