bsonのdump(文字列表現)
人間が確認するためにbsonを文字列にdumpしたいことがある。
bsonはjsonではない
bsonはjsonではないのでjson.dumpsは使えない。
import json import bson from collections import ChainMap person = ChainMap({"name": "foo"}, ChainMap({"age": 20}, {"_id": bson.ObjectId()})) try: print(json.dumps(person)) except Exception as e: print("hmm", e)
エラーになる。
hmm ChainMap({'name': 'foo'}, ChainMap({'age': 20}, {'_id': ObjectId('5950d8f10ccee07b8eb563dc')})) is not JSON serializable
json.dumpsに小細工すると見た目が悪い
json.dumpsにdefaultなどを渡して小細工をすると文字列化はできるのだけれど。例えばdictではなくChainMapやOrderedDictみたいなMappingの型の値の場合に見た目が良くない。
print(json.dumps(person, indent=2, ensure_ascii=False, default=str))
これはよくない。
"ChainMap({'name': 'foo'}, ChainMap({'age': 20}, {'_id': ObjectId('5950d9560ccee07c0ec0d91f')}))"
もう少し真面目に書くとマシにはなる。
def default(d): if hasattr(d, "keys"): return dict(d) else: return str(d) print(json.dumps(person, indent=2, ensure_ascii=False, default=default))
マシにはなる。
{ "_id": "5950d9560ccee07c0ec0d91f", "name": "foo", "age": 20 }
bson.json_utilが便利かもしれない
bson.json_utilが便利かもしれない。
import bson.json_util as u print(u.dumps(person, indent=2, ensure_ascii=False))
dumpsに対応するloadsもあったりはするのでこちらのほうが良いのかもしれない(とは言え、こちらの形式もMongoBoosterなどでおなじみの表現じゃないところがちょっと困る(もう少しbsonにencodingした時の状態に近い感じ))。
{ "name": "foo", "_id": { "$oid": "5950d99a0ccee07c50d97fd2" }, "age": 20 }