非ASCII文字を含む着信バイト文字列を有効なutf-8文字列に変換して、jsonのようにダンプできるようにしようとしています。
b = '\x80'
u8 = b.encode('utf-8')
j = json.dumps(u8)
Jは '\ xc2\x80'であると思っていましたが、代わりに次のようになります。
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)
私の状況では、「b」はmysqlからgoogleプロトコルバッファを介して取得され、いくつかのblobデータで埋められます。
何か案は?
編集:mysqlテーブルにblobとして格納されているイーサネットフレームがあります(皆さん、トピックにとどまり、テーブルにパケットがある理由について議論しないでください)。テーブルの照合はutf-8であり、dbレイヤー(sqlalchemy、non-orm)がデータを取得し、blobをpython 'str'として格納する構造体(googleプロトコルバッファー)を作成しています。プロトコルバッファを問題なく直接使用する場合もあれば、jsonを介して同じデータを公開する必要がある場合もあります。json.dumps()が処理を実行すると、「\ x80」を置き換えることができることに気付きました。無効なユニコード文字(\ ufffd iirc)
使用しているソフトウェアAPIのドキュメントを調べる必要があります。 BLOBは頭字語です:[〜#〜] binary [〜#〜]ラージオブジェクト。
データが実際にバイナリである場合、それをUnicodeにデコードするという考えはもちろんナンセンスです。
それが実際にテキストである場合は、Unicodeにデコードするために使用するエンコーディングを知る必要があります。
次に、json.dumps(a_Python_object)
を使用します...自分でUTF-8にエンコードすると、json
は再びデコードします。
>>> import json
>>> json.dumps(u"\u0100\u0404")
'"\\u0100\\u0404"'
>>> json.dumps(u"\u0100\u0404".encode('utf8'))
'"\\u0100\\u0404"'
>>>
latin1
に関する更新:
u'\x80'
は役に立たない無意味なC1制御文字です-エンコーディングがLatin-1である可能性は非常に低いです。 Latin-1は「スネアと妄想」です。8ビットバイトはすべて、例外を発生させることなくUnicodeにデコードされます。 「動作」と「例外を発生させない」を混同しないでください。
b.decode('name of source encoding')
を使用して、Unicodeバージョンを取得します。私がそれを学んだとき、これは私にとって驚きでした。例えば:
In [123]: 'foo'.decode('latin-1')
Out[123]: u'foo'
あなたがやろうとしているのは、あるエンコーディングの文字列オブジェクトをデコードすることだと思います。そのエンコーディングが何であるか知っていますか? Unicodeオブジェクトを取得します。
unicode_b = b.decode('some_encoding')
次に、utf_8エンコーディングを使用してUnicodeオブジェクトを再エンコードし、文字列オブジェクトに戻します。
b = unicode_b.encode('utf_8')
文字列の元のエンコーディングが何であるかを知らずに、Unicodeオブジェクトをトランスレータとして使用することは確かにわかりませんが、変換が期待どおりに行われない可能性があります。 Unicodeオブジェクトは、あるエンコーディングの文字列を別のエンコーディングに変換するためのものではありません。エンコーディングが何であるかを知っていると仮定して、Unicodeオブジェクトを操作します。エンコーディングが何であるかがわからない場合は、試行錯誤せずに見つけて、エンコードされた文字列に変換し直す方法は実際にはありません。文字列オブジェクトを戻したい。