I'm building a REST API using flask. I'm using postman for testing a route that creates a new item in my database, but only if the user is logged in. The routes for registering and login are working well, the last one returns the token using flask_jwt_extended module. When I send a post request to my "/api/notes" (creates a new note in database) I get the error bellow:
" (...) raise TypeError(f'Object of type {o.class.name} '
TypeError: Object of type function is not JSON serializable"
for the request I'm using the authorization tab of postman. type: Bearer Token, and my token in the field (tried with and without quotation marks)
I had faced this error this morning, before implementing my one-many relantionship, but I got it working by replacing my VERY_LONG_TOKEN with "VERY_LONG_TOKEN" in the Barear token field. I thought that because the token includes dots, it was interpreting as a function. But after implementing the relationship, I went to test and got this error again.
my note.py file:
from flask import request, Response, jsonify
from app.models import User, Note
from flask_restful import Resource
from flask_jwt_extended import jwt_required, get_jwt_identity
class NotesApi(Resource):
def get(self):
notes = Note.objects().to_json()
return Response(notes, mimetype="application/json", status=200)
@jwt_required
def post(self): # post method I'm making a request for
print("fool") # this doesn't get printed -> not reaching
user_id = get_jwt_identity()
data = request.get_json(force=True)
if data:
user = User.objects(id=user_id) # logged in user
note = Note(**data, user_author=user) # creates note with the author
note.save()
user.update(push__notes=note) # add this note to users notes
user.save()
id = str(note.id)
return {'id': id}, 200
else:
return {'error': 'missing data'}, 400
my models.py:
from app import db # using mongodb
from datetime import datetime
from flask_bcrypt import generate_password_hash, check_password_hash
class Note(db.Document):
title = db.StringField(max_length=120,required=True)
content = db.StringField(required=True)
status = db.BooleanField(required=True, default=False)
date_modified = db.DateTimeField(default=datetime.utcnow)
user_author = db.ReferenceField('User')
class User(db.Document):
username = db.StringField(max_length=100, required=True, unique=True)
email = db.StringField(max_length=120, required=True, unique=True)
password = db.StringField(required=True)
remember_me = db.BooleanField(default=False)
notes = db.ListField(db.ReferenceField('Note', reverse_delete_rule=db.PULL)) # one-many relationship
def hash_password(self):
self.password = generate_password_hash(self.password).decode('utf8')
def check_password(self, password):
return check_password_hash(self.password, password)
User.register_delete_rule(Note, 'user_author', db.CASCADE)
init.py:
from flask import Flask
from config import Config # my config class to set MONGOBD_HOST and SECRET_CLASS
from flask_mongoengine import MongoEngine
from flask_restful import Api
from flask_bcrypt import Bcrypt
from flask_jwt_extended import JWTManager
app = Flask(__name__)
app.config.from_object(Config)
db = MongoEngine(app)
api = Api(app)
bcrypt = Bcrypt(app)
jwt = JWTManager(app)
from app.resources.routes import initialize_routes
initialize_routes(api)
resources/routes.py:
from .note import NotesApi, NoteApi
from .auth import SignupApi, LoginApi
def initialize_routes(api):
api.add_resource(NotesApi, '/api/notes')
api.add_resource(NoteApi, '/api/note/<id>')
api.add_resource(SignupApi, '/api/auth/signup')
api.add_resource(LoginApi, '/api/auth/login')
folder structure:
app
|_ resources
|_ auth.py # signup working well, login also working, return a token (type = String)
|_ note.py
|_ routes.py
|_ __init__.py
|_ models.py
config.py
appname.py #just import app and do a app.run()
body of my post request:
{
"title": "test0",
"content": "test0"
}
Did anyone faced it before or know how to solve it?
Edit: added more code info
The Python "TypeError: Object of type function is not JSON serializable" occurs when we try to serialize a function to JSON. To solve the error, make sure to call the function and serialize the object that the function returns. Here is an example of how the error occurs.
The Python "TypeError: Object of type set is not JSON serializable" occurs when we try to convert a set object to a JSON string. To solve the error, convert the set to a list before serializing it to JSON, e.g. json.dumps (list (my_set)). Here is an example of how the error occurs.
Write custom JSONEncoder to make class JSON serializable. Python json module has a JSONEncoder class. You can extend it If you want more customized output. i.e., you will have to subclass JSONEncoder so you can implement your custom JSON serialization. The json.dump() and json.dumps() method of the JSON module has a cls kwarg.
The built-in json module of Python can only handle Python primitives types that have a direct JSON equivalent. i.e., The fundamental problem is that the JSON encoder json.dump () and json.dumps () only knows how to serialize the basic set of object types by default (e.g., dictionary, lists, strings, numbers, None, etc.).
Looks like flask-jwt-extended released a new version over the weekend. As part of the API changes, the @jwt_required
decorator is now @jwt_required()
https://flask-jwt-extended.readthedocs.io/en/stable/v4_upgrade_guide/#api-changes
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With