【问题标题】:Flask-PyMongo - Object of type InsertOneResult is not JSON serializableFlask-PyMongo - InsertOneResult 类型的对象不是 JSON 可序列化的
【发布时间】:2019-03-05 07:19:02
【问题描述】:

我有一个 api,我正在尝试使用 Flask-Pymongo 存储/发布用户对象。

但是,我收到以下错误

文件 "/home/kay/.local/share/virtualenvs/server-iT4jZt3h/lib/python3.7/site-packages/flask/json/i│ nit.py",第 321 行,在 jsonify
│ 转储(数据,缩进=缩进,分隔符=分隔符)+'\n',│文件 "/home/kay/.local/share/virtualenvs/server-iT4jZt3h/lib/python3.7/site-packages/flask/json/i│ nit.py",第 179 行,在转储中
│ rv = _json.dumps(obj, **kwargs) │ 文件“/usr/lib/python3.7/json/init.py”,第 238 行,转储
│ **kw).encode(obj) │ 文件“/usr/lib/python3.7/json/encoder.py”,第201行,在encode
│ chunks = list(chunks) │ 文件“/usr/lib/python3.7/json/encoder.py”,第 438 行,在 _iterencode │ o = _default(o) │ 文件“/home/kay/link/server/src/run.py”,第 18 行,默认
│ return json.JSONEncoder.default(self, o) │ File "/usr/lib/python3.7/json/encoder.py", line 179, in default
│ raise TypeError(f'Object of type {o.class.name} ' │ TypeError: Object of InsertOneResult is not JSON serializable

app/users/resource.py

from flask_restful import Resource
from flask import jsonify, request
from .repository import UsersRepository
from db import mongo


class UsersResource(Resource):

    def __init__(self):

        self.repository = UsersRepository()

    def get(self):

        data = {"Users": "Resource"}
        res = data, 200
        return res

    def post(self):

        req = request.get_json()

        user = {
            "email": req.get("email"),
            "password": req.get("password")
        }

        result = mongo.db.users.insert_one(user)

        return jsonify(result)

run.py

from flask import Flask
from app import api_bp
from db import mongo
from bson.objectid import ObjectId
import json
import datetime
import os

class JSONEncoder(json.JSONEncoder):

    def default(self, o):
        if isinstance(o, ObjectId):
            return str(o)
        if isinstance(o, set):
            return list(o)
        if isinstance(o, datetime.datetime):
            return str(o)
        return json.JSONEncoder.default(self, o)



def create_app(config_filename):

    app = Flask(__name__)
    app.config.from_object(config_filename)
    app.register_blueprint(api_bp, url_prefix='/api')

    mongo.init_app(app)

    app.json_encoder = JSONEncoder

    return app


# def logger():


# def database():


if __name__ == "__main__":
    app = create_app("config")
    app.run(host='0.0.0.0', port=8080, debug=True)

【问题讨论】:

  • 请在此处粘贴回溯!
  • 我更新了@Feng的问题
  • insert_one 方法返回一个 InsertOneResult 的实例,它不是 JSON 可序列化的,如回溯中所示。您可能想要返回 inserted_id

标签: python flask pymongo flask-pymongo


【解决方案1】:

我相信按照之前的建议您可以找到答案。但我想提供另一种简化它的解决方案。

该解决方案假定安装了pymongoflask 包:

from flask import Flask
from flask.json import JSONEncoder

from bson import json_util

from . import resources

# define a custom encoder point to the json_util provided by pymongo (or its dependency bson)
class CustomJSONEncoder(JSONEncoder):
    def default(self, obj): return json_util.default(obj)

application = Flask(__name__)
application.json_encoder = CustomJSONEncoder

if __name__ == "__main__":
    application.run()

【讨论】:

    【解决方案2】:

    TypeError: Object of type InsertOneResult is not JSON serializable 行描述了问题。 insert_one() 返回一个 InsertOneResult object,其中包含插入的 ID(如 @styvane 的评论所建议的那样)以及指示写入是否被数据库确认的标志。其他操作有类似的结果对象,都不是 JSON 可序列化的。

    Flask-PyMongo 的未来版本可能会添加助手来支持这一点,您可以关注https://github.com/dcrosta/flask-pymongo/issues/62 来添加想法和建议。

    【讨论】:

      【解决方案3】:
      1. 从 bson.objectid 导入 ObjectId
      2. 从 bson 导入 json_util

        • 使用 pymongo json_util bson 处理 BSON 类型
      3. 获取 json 输入时使用 force=true :

        • req = request.get_json(force=true)
      4. 在获取 dict 字段时使用默认值,例如:
        • req.get("email", "")

      您可以在插入 mongo 之前检查字段是否为空。

      【讨论】:

        【解决方案4】:

        我从这里找到的简单解决方案是

        TypeError: ObjectId('') is not JSON serializable

        响应 -> bson 转储(序列化)-> json 加载(反序列化)

        代码如下:

        from bson.json_util import dumps,RELAXED_JSON_OPTIONS
        import json
        
        
        def post(self,name):
                dream = {'name':name , 'price' : 12.00 }
                dreams.append(dream)
                dreamDao.addDream(dream) #MongoDB Call to Insert Data 
                bs = dumps(dream,json_options=RELAXED_JSON_OPTIONS) #Now dream has Response Which will have ObjectId
                return json.loads(bs) , 201
        

        【讨论】:

          【解决方案5】:
          from flask_pymongo import Pymongo
          import json
          import pandas as pd
          
          user = pd.DataFrame(user)
          
          mongo.db.users.insert_one({'email':json.loads(user[0].to_json(orient='index')),                            
                                 'password':json.loads(user[1].to_json(orient='index'))})
          

          如果您的对象已经是 json,这将引发错误。如果不是,它会将它们转换为 json 并一次性加载它们。

          【讨论】:

            【解决方案6】:

            您发布到服务器的内容似乎不是有效的 json 对象。所以你应该调试你得到的东西。

            class UsersResource(Resource):
            
                def post(self):
                    # debug
                    print("request.args is {}".format(request.args))
                    print("request.form is {}".format(request.form))
                    print("request.data is {}".format(request.data))
            
                    req = request.get_json()
            
                    user = {
                        "email": req.get("email"),
                        "password": req.get("password")
                    }
            
                    result = mongo.db.users.insert_one(user)
            
                    return jsonify(result)
            

            【讨论】:

              猜你喜欢
              • 2022-01-26
              • 2021-09-24
              • 2020-09-05
              • 2019-07-12
              • 1970-01-01
              • 2017-11-09
              • 1970-01-01
              • 1970-01-01
              • 2019-10-27
              相关资源
              最近更新 更多