【问题标题】:How to serialize ObjectId with jsonpickle in flask pymongo如何在烧瓶 pymongo 中使用 jsonpickle 序列化 ObjectId
【发布时间】:2020-07-06 04:40:39
【问题描述】:

我使用 Flask 和 MongoDB 作为数据库和 pymongo 作为驱动程序。我在使用json.dumps()json.loads()json_util.dumps() 等将对象序列化为 JSON 时遇到了麻烦,因为它总是说TypeError: Object of type 'EachRoom' is not JSON serializable。我找到了一个名为 jsonpickle 的库来将对象序列化为 JSON。除了ObjectId 字段外,它按预期完成。当我检查数据类型时,它显示为bytes 类型。这是我的代码:

class EachRoom:
    def __init__(self, id, rooms):
        self.id =  id
        self.rooms = rooms

class Room(object):
    @classmethod
    def return_all_by_user(cls):
        cursor_user = mongo.db.rooms.distinct('user_id')
        users = []

        for row in cursor_user:
            print(str(row))
            cursor_room = mongo.db.rooms.find({'user_id': ObjectId(row)})

            each = EachRoom(ObjectId(row), cursor_room)
            users.append(each)
            print(cursor_room)
        print(users)
        user = jsonpickle.encode(users, unpicklable=False)
        res_user = jsonpickle.decode(user)
        print(res_user)

        if cursor_room:
            return Response(
                json_util.dumps({'message': 'success', 'user': res_user}, json_options=json_util.RELAXED_JSON_OPTIONS),
                mimetype='application/json'
            )
        else:
            return {'message': 'Document rooms is empty'}, 404

下面是回复:

{
    "message": "success",
    "user": [
        {
            "id": {
                "$binary": {
                    "base64": "Xl/WQvzhBgBTGeiE",
                    "subType": "00"
                }
            },
            "rooms": [
                {
                    "_id": {
                        "$binary": {
                            "base64": "XngkNuL9Y6AIX04v",
                            "subType": "00"
                        }
                    },
                    "created_at": "2020-03-23 09:51:34.789000",
                    "name": "Ruang Makan",
                    "updated_at": "2020-03-23 09:51:34.789000",
                    "user_id": {
                        "$binary": {
                            "base64": "Xl/WQvzhBgBTGeiE",
                            "subType": "00"
                        }
                    }
                },
                {
                    "_id": {
                        "$binary": {
                            "base64": "XngkROL9Y6AIX04w",
                            "subType": "00"
                        }
                    },
                    "created_at": "2020-03-23 09:51:48.834000",
                    "name": "Kamar Mandi",
                    "updated_at": "2020-03-23 09:51:48.834000",
                    "user_id": {
                        "$binary": {
                            "base64": "Xl/WQvzhBgBTGeiE",
                            "subType": "00"
                        }
                    }
                },
                {
                    "_id": {
                        "$binary": {
                            "base64": "XngkTOL9Y6AIX04x",
                            "subType": "00"
                        }
                    },
                    "created_at": "2020-03-23 09:51:56.220000",
                    "name": "Kamar Tidur Utama",
                    "updated_at": "2020-03-23 09:51:56.220000",
                    "user_id": {
                        "$binary": {
                            "base64": "Xl/WQvzhBgBTGeiE",
                            "subType": "00"
                        }
                    }
                }
            ]
        },
        {
            "id": {
                "$binary": {
                    "base64": "XnYgKnLe9u63KLbG",
                    "subType": "00"
                }
            },
            "rooms": [
                {
                    "_id": {
                        "$binary": {
                            "base64": "Xnq+2G5/pNeS7ynf",
                            "subType": "00"
                        }
                    },
                    "created_at": "2020-03-25 09:15:52.819000",
                    "name": "Kamar Tidur Eren",
                    "updated_at": "2020-03-25 09:15:52.819000",
                    "user_id": {
                        "$binary": {
                            "base64": "XnYgKnLe9u63KLbG",
                            "subType": "00"
                        }
                    }
                },
                {
                    "_id": {
                        "$binary": {
                            "base64": "Xnq+6W5/pNeS7yng",
                            "subType": "00"
                        }
                    },
                    "created_at": "2020-03-25 09:16:09.683000",
                    "name": "Kamar Tidur Utama",
                    "updated_at": "2020-03-25 09:16:09.683000",
                    "user_id": {
                        "$binary": {
                            "base64": "XnYgKnLe9u63KLbG",
                            "subType": "00"
                        }
                    }
                },
                {
                    "_id": {
                        "$binary": {
                            "base64": "Xnq+8G5/pNeS7ynh",
                            "subType": "00"
                        }
                    },
                    "created_at": "2020-03-25 09:16:16.262000",
                    "name": "Kamar Mandi",
                    "updated_at": "2020-03-25 09:16:16.262000",
                    "user_id": {
                        "$binary": {
                            "base64": "XnYgKnLe9u63KLbG",
                            "subType": "00"
                        }
                    }
                }
            ]
        }
    ]
}

唯一出错的是iduser_id_id 作为ObjectId 类型。需要建议..

【问题讨论】:

  • 检查这个JSON serializing Mongodb。也许您对更适合您的代码的MongoEngine 感兴趣。 MongoEngine 有方法 to_json 可以正确序列化 BSON 对象(ObjectId、DbRef 等...)
  • @Valijon 谢谢,但根据this answer 的说法,他不推荐 mongoengine,因为它不再维护,太多错误,并且有很多意外行为。我应该吗?
  • 这是个人意见,没有提供证据。它是官方认可的MongoDB driver 之一,并由社区积极维护

标签: json mongodb flask pymongo jsonpickle


【解决方案1】:

三招合一:

  • 要将类对象加载到 MongoDB 中,请使用该类的内置 __dict__ 属性。
  • 要将您的 BSON 转换为 JSON,请使用来自 bson.json_util 模块的转储
  • 最终避免使用id作为变量;这是一个python函数。

这里有一个小样本可供尝试:

from pymongo import MongoClient
from bson import ObjectId
from bson.json_util import dumps

db = MongoClient()['mydatabase']

class EachRoom:
    def __init__(self, room_id, rooms):
        self.id = room_id
        self.rooms = rooms

room1 = EachRoom(ObjectId("123456789012345678901234"), '1')
db.rooms.insert_one(room1.__dict__)
print(dumps(db.rooms.find_one()))

给予:

{"_id": {"$oid": "5e7b8d7ebf681e2e5ecb6059"}, "id": {"$oid": "123456789012345678901234"}, "rooms": "1"}

【讨论】:

  • 哇,您的__dict__ 提示帮助了我,尽管其余的与我的代码无关。感谢您的提示!
猜你喜欢
  • 2018-10-10
  • 2018-03-26
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 2015-10-25
  • 1970-01-01
相关资源
最近更新 更多