0

i'm creating an API in python + Flask + marshmallow. Here's the class + the first function (i don't already use the others )

import datetime
from marshmallow import Schema, fields, ValidationError, pre_load
from flask import Flask, jsonify
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy
from flask import request
import os


app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'User.sqlite')
# Order matters: Initialize SQLAlchemy before Marshmallow
db = SQLAlchemy(app)
ma = Marshmallow(app)





class User(db.Model):
    userid = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(30))
    badgenum = db.Column(db.String(30))
    mail = db.Column(db.String(30))
    status = db.Column(db.String(30))
    admin = db.Column(db.String(30))

    def __init__(self, userid, name, badgenum, mail, status, admin):
        self.userid = userid
        self.name = name
        self.badgenum = badgenum
        self.mail = mail
        self.status = status
        self.admin = admin


class UserSchema(ma.Schema):
    class Meta:
        fields = ('userid', 'name', 'badgenum', 'mail', 'status', 'admin')


user_schema = UserSchema()
users_schema = UserSchema(many=True)


@app.route("/User", methods=["POST"])
def add_User():
    userid = request.json['userid']
    name = request.json['name']
    badgenum = request.json['badgenum']
    mail = request.json['mail']
    status = request.json['status']
    admin = request.json['admin']


    new_user = User(userid, name, badgenum, mail, status, admin)

    db.session.add(new_user)
    db.session.commit()

    return jsonify(new_user)

I tested the function add_User using Postman with this json request :

{

    "userid" : 1,
    "name" : "name1",
    "badgenum" : "66897",
    "mail" : "ghh@orange.fr",
    "status" : "on",
    "admin" : "f"

}

and i got this error:

TypeError: <User 145> is not JSON serializable
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
JeanSec
  • 11
  • 1
  • 6

1 Answers1

3

User has its own autogenerated id user.id which is ObjectId. You need custom json encoder to encode ObjectId field.

import json, bson

def json_response(obj, cls=None):
    response = make_response(json.dumps(obj, cls=cls))
    response.content_type = 'application/json'

    return response

class MongoJsonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, bson.ObjectId):
            return str(obj)

        return json.JSONEncoder.default(self, obj)

Now try to call return json_response(new_user, cls=MongoJsonEncoder)

Alk
  • 161
  • 3
  • 1
    Actually, you have a misleading title. It says ` is not JSON serializable` and then in post `TypeError: is not JSON serializable`. You are passing user object to jsonify, but it accepts values like dictionaries. First, you need to convert user obj to a dictionary. Try `return jsonify(name=new_user.name)` – Alk Feb 01 '18 at 14:09
  • it is working!!!!! nice but i don't understand what you're saying about dictionnaries I cannot jsonify an object? – JeanSec Feb 01 '18 at 14:16
  • It depends on the object. Objects are very different from each other and one function cant serve them all. – Alk Feb 01 '18 at 14:25
  • Thanks, @Alk. Converting the object to a dict worked for me. return jsonify(name=new_user.name) – Natacha May 19 '18 at 17:30