0

Python 2.7を使用してdictオブジェクトをjson文字列にシリアル化しようとしていますjson(例:) import json

Example:
json.dumps({
    'property1':        'A normal string',
    'pickled_property': \u0002]qu0000U\u0012
})

オブジェクトには、を使用して「ピクルス化」されたデータであるいくつかのバイト文字列が含まれているcPickleため、jsonの目的では、これらは基本的にランダムなバイト文字列です。私はdjango.utilsを使用していましたがsimplejson、これは問題なく機能しました。しかし、最近Google AppEngineでPython2.7に切り替えたところ、simplejsonが利用できなくなったようです。

を使用しjsonているので、UTF-8の一部ではないバイトが検出されると、例外がスローされます。私が得ているエラーは次のとおりです。

UnicodeDecodeError:'utf8'コーデックは位置0のバイト0x80をデコードできません:無効な開始バイト

デバッグのように文字コードの文字列を出力すると便利です。つまり、次のようになります\u0002]q\u0000U\u001201。しかし、例外をスローせず、認識した情報をシリアル化し続ける限り、このデータをどのように処理するかはあまり気にしません。

どうすればこれを実現できますか?

ありがとう!

4

1 に答える 1

2

JSON仕様では、文字列をUnicode文字で定義しています。このため、モジュールは、受信しjsonたすべてのインスタンスがエンコードされたユニコードテキストを保持していると想定します。strデフォルトのエンコーディングとしてUTF-8を試行します。これにより、出力のような文字列がpickle.dumps有効なUTF-8シーケンスではない場合に問題が発生します。

幸い、問題の修正は簡単です。json.dumpsUTF-8の代わりに使用するエンコーディングを関数に指示するだけです。my_bytestring有効なUTF-8テキストではありませんが、以下は機能します。

import json, cPickle as pickle

my_data = ["some data", 1, 2, 3, 4]
my_bytestring = pickle.dumps(my_data, pickle.HIGHEST_PROTOCOL)
json_data = json.dumps(my_bytestring, encoding="latin-1")

ここで使用されている代わりに、8ビットエンコーディングが機能すると思いlatin-1ます(後でデコードする場合は、必ず同じものを使用してください)。

JSONでエンコードされたデータの選択を解除する場合は、を呼び出す必要があります。これはunicode.decodejson.loads常にエンコードされた文字列をunicodeインスタンスとして返すためです。したがって、my_dataリストをjson_data上記から戻すには、次のコードが必要です。

my_unicode_data = json.loads(json_data)
my_new_bytestring = my_unicode_data.encode("latin-1")  # equal to my_bytestring
my_new_data = pickle.loads(my_new_bytestring)          # equal to my_data
于 2012-09-07T06:32:11.070 に答える