我一直在开发一个简单的app.py,代码如下:
from flask import Flask, request, jsonify, make_response
from pymongo import MongoClient
from bson import ObjectId
app = Flask(__name__)
client = MongoClient("mongodb://127.0.0.1:27017")
db = client.bizDB
businesses = db.biz
@app.route("/api/v1.0/businesses", methods=["GET"])
def show_all_businesses():
page_num, page_size = 1, 10
if request.args.get("pn"):
page_num = int(request.args.get("pn"))
if request.args.get("ps"):
page_size = int(request.args.get("ps"))
page_start = page_size * (page_num - 1)
data_to_return = []
for business in businesses.find().skip(page_start).limit(page_size):
business["_id"] = str(business["_id"])
for review in business["reviews"]:
review["_id"] = str(review["_id"])
data_to_return.append(business)
return make_response(jsonify(data_to_return), 200)
@app.route("/api/v1.0/businesses/<string:id>", methods=["GET"])
def show_one_business(id):
business = businesses.find_one({"_id": ObjectId(id)})
if business is not None:
business["_id"] = str(business["_id"])
for review in business["reviews"]:
review["_id"] = str(review["_id"])
return make_response(jsonify(business), 200)
else:
return make_response(jsonify({"error": "Invalid Business ID"}), 404)
@app.route("/api/v1.0/businesses", methods=["POST"])
def add_business():
if "name" in request.form and "town" in request.form and "rating" in request.form:
new_business = {"name": request.form["name"],
"town": request.form["town"],
"rating": request.form["rating"],
"reviews": {}
}
new_business_id = businesses.insert_one(new_business)
new_business_link = "http://localhost:5000/api/v1.0/businesses/" + \
str(new_business_id.inserted_id)
return make_response(jsonify({"url": new_business_link}), 201)
else:
return make_response(jsonify({"error": "Missing form data"}), 404)
@app.route("/api/v1.0/businesses/<string:id>", methods=["PUT"])
def edit_business(id):
if "name" in request.form and "town" in request.form and "rating" in request.form:
result = businesses.update_one(
{"_id": ObjectId(id)},
{
"$set": {
"name": request.form["name"],
"town": request.form["town"],
"rating": request.form["rating"]
}
}
)
if result.matched_count == 1:
edited_business_link = "http://localhost:5000/api/v1.0/businesses/" + id
return make_response(jsonify({"url": edited_business_link}), 200)
else:
return make_response(jsonify({"error": "Invalid business ID"}), 404)
else:
return make_response(jsonify({"error": "Missing form data"}), 404)
@app.route("/api/v1.0/businesses/<string:id>", methods=["DELETE"])
def delete_business(id):
result = businesses.delete_one({"_id": ObjectId(id)})
if result.deleted_count == 1:
return make_response(jsonify({}), 200)
else:
return make_response(jsonify({"error": "Invalid business ID"}), 404)
@app.route("/api/v1.0/businesses/<string:id>/reviews", methods=["POST"])
def add_new_review(id):
new_review = {
"_id": ObjectId(),
"username": request.form["username"],
"comment": request.form["comment"],
"stars": request.form["stars"]
}
businesses.update_one({"_id": ObjectId(id)}, {
"$push": {"reviews ": new_review}})
new_review_link = "http://localhost:5000/api/v1.0/businesses/" + \
id + "/reviews/" + str(new_review["_id"])
return make_response(jsonify({"url": new_review_link}), 201)
if __name__ == "__main__":
app.run(debug=True)
Eveyrthing 一直运行良好,直到在 VS Code 中我不小心在文件上单击了格式化文档,Postman 之前从 mongoDB 返回了我的结果,但现在我收到了 TypeError 错误:ObjectId 类型的对象不是 JSON 可序列化的。
>我不知道如何解决这个问题或问题是什么。
答案 0 :(得分:0)
您的根本原因是在您返回的响应中,该对象包含一个 ObjectId
类型的字段,该字段始终是 _id
字段。
要全面修复它,请使用我们自己的自定义 JSON 编码器,该编码器可自动将 ObjectId
转换为字符串。一旦你有了这个,你的代码就会整理很多,因为你可以删除所有需要手动进行转换的代码。
示例编码器如下所示:
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, ObjectId):
return str(obj)
return super(MyEncoder, self).default(obj)
并且你让flask知道使用它:
app.json_encoder = MyEncoder
把它们放在一起,一个最小的例子是:
from pymongo import MongoClient
from flask import Flask, jsonify
from bson.json_util import ObjectId
import json
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, ObjectId):
return str(obj)
return super(MyEncoder, self).default(obj)
db = MongoClient()['mydatabase']
app = Flask(__name__)
app.json_encoder = MyEncoder
with app.test_request_context():
db.mycollection.insert_one({'a': 1})
doc = db.mycollection.find_one({'a': 1})
print(jsonify(doc).response)
印刷品:
[b'{"_id":"5ff055dffab2033526bd0b63","a":1}\n']
注意:如果您注释掉 app.json_encoder = MyEncoder
行,则会重现您的错误:
return _json.JSONEncoder.default(self, o)
File "C:\Python38\lib\json\encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type ObjectId is not JSON serializable