Flask-PyMongo - Object of type InsertOneResult is not JSON serializable

喜夏-厌秋 提交于 2019-12-02 22:27:11

问题


i have an api and i am trying to store/post a user object using Flask-Pymongo.

but, i get the following error

File "/home/kay/.local/share/virtualenvs/server-iT4jZt3h/lib/python3.7/site-packages/flask/json/i│ nit.py", line 321, in jsonify
│ dumps(data, indent=indent, separators=separators) + '\n', │ File "/home/kay/.local/share/virtualenvs/server-iT4jZt3h/lib/python3.7/site-packages/flask/json/i│ nit.py", line 179, in dumps
│ rv = _json.dumps(obj, **kwargs) │ File "/usr/lib/python3.7/json/init.py", line 238, in dumps
│ **kw).encode(obj) │ File "/usr/lib/python3.7/json/encoder.py", line 201, in encode
│ chunks = list(chunks) │ File "/usr/lib/python3.7/json/encoder.py", line 438, in _iterencode │ o = _default(o) │ File "/home/kay/link/server/src/run.py", line 18, in default
│ 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 type 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)

回答1:


  1. from bson.objectid import ObjectId
  2. from bson import json_util

    • use pymongo json_util bson to handle BSON types
  3. use force=true when getting json input :

    • req = request.get_json(force=true)
  4. use default values when getting dict fields like :
    • req.get("email", "")

you can check if fields are empty or not before inserting into mongo.




回答2:


Simple Solution I found from here is

TypeError: ObjectId('') is not JSON serializable

Response -> bson dumps (searlization) -> json loads (deserialization)

Code is as follows :

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



回答3:


The line TypeError: Object of type InsertOneResult is not JSON serializable describes the problem. insert_one() returns an InsertOneResult object, which contains the inserted ID (as @styvane's comment suggested) as well as a flag indicating whether the write was ack'd by the database. Other operations have similar result objects, and none of them are JSON serializable.

A future version of Flask-PyMongo may add helpers to support this, you can follow https://github.com/dcrosta/flask-pymongo/issues/62 to add ideas and suggestions.




回答4:


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'))})

This will throw up errors if your objects are already json. If they aren't though, it'll turn them into json and load them all in one go.




回答5:


I believe that following previous suggestion you can find the answers. But I would like to provide another solution that simplifies it.

The solution assumes that pymongo and flask packages are installed:

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()




回答6:


It seems that what you post to server is not a valid json object. So you should debug what you got.

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)


来源:https://stackoverflow.com/questions/52569791/flask-pymongo-object-of-type-insertoneresult-is-not-json-serializable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!