web-dev-qa-db-fra.com

Comment sérialiser le résultat SqlAlchemy en JSON?

Django a une bonne sérialisation automatique des modèles ORM renvoyés du format DB au format JSON.

Comment sérialiser le résultat d'une requête SQLAlchemy au format JSON? 

J'ai essayé jsonpickle.encode mais il code l'objet de requête lui-même . J'ai essayé json.dumps(items) mais il retourne

TypeError: <Product('3', 'some name', 'some desc')> is not JSON serializable

Est-ce vraiment si difficile de sérialiser des objets SQLAlchemy ORM en JSON/XML? N'y a-t-il pas de sérialiseur par défaut pour cela? Il est très courant de sérialiser les résultats des requêtes ORM de nos jours.

Ce dont j'ai besoin est simplement de renvoyer la représentation de données JSON ou XML du résultat de la requête SQLAlchemy.

Le résultat de la requête sur les objets SQLAlchemy au format JSON/XML doit être utilisé dans javascript datagird (JQGrid http://www.trirand.com/blog/ ).

132
Zelid

Une mise en œuvre à plat

Vous pouvez utiliser quelque chose comme ceci:

from sqlalchemy.ext.declarative import DeclarativeMeta

class AlchemyEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # an SQLAlchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                data = obj.__getattribute__(field)
                try:
                    json.dumps(data) # this will fail on non-encodable values, like other classes
                    fields[field] = data
                except TypeError:
                    fields[field] = None
            # a json-encodable dict
            return fields

        return json.JSONEncoder.default(self, obj)

puis convertir en JSON en utilisant:

c = YourAlchemyClass()
print json.dumps(c, cls=AlchemyEncoder)

Il ignorera les champs non codables (définissez-les sur «Aucun»).

Cela n'élargit pas automatiquement les relations (car cela pourrait conduire à des auto-références et une boucle pour toujours).

Une implémentation récursive non circulaire

Si, toutefois, vous préférez rester en boucle pour toujours, vous pouvez utiliser:

from sqlalchemy.ext.declarative import DeclarativeMeta

def new_alchemy_encoder():
    _visited_objs = []

    class AlchemyEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj.__class__, DeclarativeMeta):
                # don't re-visit self
                if obj in _visited_objs:
                    return None
                _visited_objs.append(obj)

                # an SQLAlchemy class
                fields = {}
                for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                    fields[field] = obj.__getattribute__(field)
                # a json-encodable dict
                return fields

            return json.JSONEncoder.default(self, obj)

    return AlchemyEncoder

Et ensuite, encodez les objets en utilisant:

print json.dumps(e, cls=new_alchemy_encoder(), check_circular=False)

Cela encoderait tous les enfants, et tous leurs enfants, et tous leurs enfants ... En fait, encodez potentiellement toute votre base de données. Quand il atteint quelque chose de son encodé avant, il le codera comme «Aucun».

Une implémentation sélective récursive, éventuellement circulaire

Une autre alternative, probablement meilleure, consiste à pouvoir spécifier les champs que vous souhaitez développer:

def new_alchemy_encoder(revisit_self = False, fields_to_expand = []):
    _visited_objs = []

    class AlchemyEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj.__class__, DeclarativeMeta):
                # don't re-visit self
                if revisit_self:
                    if obj in _visited_objs:
                        return None
                    _visited_objs.append(obj)

                # go through each field in this SQLalchemy class
                fields = {}
                for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                    val = obj.__getattribute__(field)

                    # is this field another SQLalchemy object, or a list of SQLalchemy objects?
                    if isinstance(val.__class__, DeclarativeMeta) or (isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
                        # unless we're expanding this field, stop here
                        if field not in fields_to_expand:
                            # not expanding this field: set it to None and continue
                            fields[field] = None
                            continue

                    fields[field] = val
                # a json-encodable dict
                return fields

            return json.JSONEncoder.default(self, obj)

    return AlchemyEncoder

Vous pouvez maintenant l'appeler avec:

print json.dumps(e, cls=new_alchemy_encoder(False, ['parents']), check_circular=False)

Pour ne développer que les champs SQLAlchemy appelés «parents», par exemple.

107
Sasha B

Vous pouvez simplement sortir votre objet sous forme de dict:

class User:
   def as_dict(self):
       return {c.name: getattr(self, c.name) for c in self.__table__.columns}

Et ensuite, vous utilisez User.as_dict () pour sérialiser votre objet.

Comme expliqué dans Convertissez un objet row sqlalchemy en dict python

207
charlax

Vous pouvez convertir un RowProxy en un dict comme ceci:

 d = dict(row.items())

Puis sérialisez cela en JSON (vous devrez spécifier un encodeur pour des choses comme les valeurs datetime) Ce n'est pas si difficile si vous voulez juste un enregistrement (et non une hiérarchie complète d'enregistrements liés).

json.dumps([(dict(row.items())) for row in rs])
43
Nick Perkins

Je recommande d'utiliser une bibliothèque récente/ Marshmallow . Il vous permet de créer des sérialiseurs pour représenter vos instances de modèle avec une prise en charge des relations et des objets imbriqués.

Jetez un coup d'œil à theier Exemple SQLAlchemy .

34
Yasir Hantoush

Flask-JsonTools package a une implémentation de JsonSerializableBase Classe de base pour vos modèles.

Usage:

from sqlalchemy.ext.declarative import declarative_base
from flask.ext.jsontools import JsonSerializableBase

Base = declarative_base(cls=(JsonSerializableBase,))

class User(Base):
    #...

Le modèle User est maintenant sérialisable comme par magie.

Si votre framework n'est pas Flask, vous pouvez simplement saisir le code

14
kolypto

Pour des raisons de sécurité, vous ne devez jamais renvoyer tous les champs du modèle. Je préfère les choisir de manière sélective.

Le codage json de Flask prend désormais en charge les UUID, la date et l'heure et les relations (et les query et query_class ajoutés pour la classe flask_sqlalchemy db.Model). J'ai mis à jour le codeur comme suit:

app/json_encoder.py

    from sqlalchemy.ext.declarative import DeclarativeMeta
    from flask import json


    class AlchemyEncoder(json.JSONEncoder):
        def default(self, o):
            if isinstance(o.__class__, DeclarativeMeta):
                data = {}
                fields = o.__json__() if hasattr(o, '__json__') else dir(o)
                for field in [f for f in fields if not f.startswith('_') and f not in ['metadata', 'query', 'query_class']]:
                    value = o.__getattribute__(field)
                    try:
                        json.dumps(value)
                        data[field] = value
                    except TypeError:
                        data[field] = None
                return data
            return json.JSONEncoder.default(self, o)

app/__init__.py

# json encoding
from app.json_encoder import AlchemyEncoder
app.json_encoder = AlchemyEncoder

Avec cela, je peux éventuellement ajouter une propriété __json__ qui renvoie la liste des champs que je souhaite encoder:

app/models.py

class Queue(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    song_id = db.Column(db.Integer, db.ForeignKey('song.id'), unique=True, nullable=False)
    song = db.relationship('Song', lazy='joined')
    type = db.Column(db.String(20), server_default=u'audio/mpeg')
    src = db.Column(db.String(255), nullable=False)
    created_at = db.Column(db.DateTime, server_default=db.func.now())
    updated_at = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now())

    def __init__(self, song):
        self.song = song
        self.src = song.full_path

    def __json__(self):
        return ['song', 'src', 'type', 'created_at']

J'ajoute @jsonapi à ma vue, renvoie la liste de résultats, puis mon résultat est le suivant:

[

{

    "created_at": "Thu, 23 Jul 2015 11:36:53 GMT",
    "song": 

        {
            "full_path": "/static/music/Audioslave/Audioslave [2002]/1 Cochise.mp3",
            "id": 2,
            "path_name": "Audioslave/Audioslave [2002]/1 Cochise.mp3"
        },
    "src": "/static/music/Audioslave/Audioslave [2002]/1 Cochise.mp3",
    "type": "audio/mpeg"
}

]
11
Tjorriemorrie

Vous pouvez utiliser l'introspection de SqlAlchemy comme ceci: 

mysql = SQLAlchemy()
from sqlalchemy import inspect

class Contacts(mysql.Model):  
    __table= 'CONTACTS'
    id = mysql.Column(mysql.Integer, primary_key=True)
    first_name = mysql.Column(mysql.String(128), nullable=False)
    last_name = mysql.Column(mysql.String(128), nullable=False)
    phone = mysql.Column(mysql.String(128), nullable=False)
    email = mysql.Column(mysql.String(128), nullable=False)
    street = mysql.Column(mysql.String(128), nullable=False)
    Zip_code = mysql.Column(mysql.String(128), nullable=False)
    city = mysql.Column(mysql.String(128), nullable=False)
    def toDict(self):
        return { c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs }

@app.route('/contacts',methods=['GET'])
def getContacts():
    contacts = Contacts.query.all()
    contactsArr = []
    for contact in contacts:
        contactsArr.append(contact.toDict()) 
    return jsonify(contactsArr)

@app.route('/contacts/<int:id>',methods=['GET'])
def getContact(id):
    contact = Contacts.query.get(id)
    return jsonify(contact.toDict())

Laissez-vous inspirer par une réponse ici: Convertit un objet de la ligne sqlalchemy en Python dict

8
phico

Une explication plus détaillée. Dans votre modèle, ajoutez: 

def as_dict(self):
       return {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}

str() est pour python 3, donc si vous utilisez python 2, utilisez unicode(). Cela devrait aider à désérialiser les dates. Vous pouvez l'enlever si vous ne vous en occupez pas.

Vous pouvez maintenant interroger la base de données comme ceci

some_result = User.query.filter_by(id=current_user.id).first().as_dict()

First() est nécessaire pour éviter des erreurs étranges. as_dict() va maintenant désérialiser le résultat. Après désérialisation, il est prêt à être transformé en json

jsonify(some_result)
4
Patrick Mutuku

Ce n'est pas si simple. J'ai écrit du code pour le faire. Je travaille toujours dessus, et il utilise le framework MochiKit. Il traduit essentiellement les objets composés entre Python et Javascript à l'aide d'un proxy et de convertisseurs JSON enregistrés. 

Le côté navigateur pour les objets de base de données est db.js Il a besoin de la source proxy Python de base dans proxy.js .

Du côté de Python, il y a le module de base proxy . Puis enfin le codeur d’objet SqlAlchemy dans webserver.py . Il dépend également des extracteurs de métadonnées trouvés dans le fichier models.py. fichier.

3
Keith

Voici une solution qui vous permet de sélectionner les relations que vous souhaitez inclure dans votre sortie aussi profondément que vous le souhaitez. NOTE: Il s'agit d'une réécriture complète prenant un dict/str comme argument plutôt que comme une liste. . corrige quelques trucs ..

def deep_dict(self, relations={}):
    """Output a dict of an SA object recursing as deep as you want.

    Takes one argument, relations which is a dictionary of relations we'd
    like to pull out. The relations dict items can be a single relation
    name or deeper relation names connected by sub dicts

    Example:
        Say we have a Person object with a family relationship
            person.deep_dict(relations={'family':None})
        Say the family object has homes as a relation then we can do
            person.deep_dict(relations={'family':{'homes':None}})
            OR
            person.deep_dict(relations={'family':'homes'})
        Say homes has a relation like rooms you can do
            person.deep_dict(relations={'family':{'homes':'rooms'}})
            and so on...
    """
    mydict =  dict((c, str(a)) for c, a in
                    self.__dict__.items() if c != '_sa_instance_state')
    if not relations:
        # just return ourselves
        return mydict

    # otherwise we need to go deeper
    if not isinstance(relations, dict) and not isinstance(relations, str):
        raise Exception("relations should be a dict, it is of type {}".format(type(relations)))

    # got here so check and handle if we were passed a dict
    if isinstance(relations, dict):
        # we were passed deeper info
        for left, right in relations.items():
            myrel = getattr(self, left)
            if isinstance(myrel, list):
                mydict[left] = [rel.deep_dict(relations=right) for rel in myrel]
            else:
                mydict[left] = myrel.deep_dict(relations=right)
    # if we get here check and handle if we were passed a string
    Elif isinstance(relations, str):
        # passed a single item
        myrel = getattr(self, relations)
        left = relations
        if isinstance(myrel, list):
            mydict[left] = [rel.deep_dict(relations=None)
                                 for rel in myrel]
        else:
            mydict[left] = myrel.deep_dict(relations=None)

    return mydict

donc pour un exemple utilisant personne/famille/maisons/chambres ... en le transformant en json tout ce dont vous avez besoin est

json.dumps(person.deep_dict(relations={'family':{'homes':'rooms'}}))
2
tahoe

Bien que la question initiale remonte à un moment, le nombre de réponses fournies ici (ainsi que ma propre expérience) suggèrent que c'est une question non triviale avec beaucoup d'approches différentes de complexité variable avec différents compromis.

C'est pourquoi j'ai construit la bibliothèque SQLAthanor qui étend l'ORM déclaratif de SQLAlchemy avec une prise en charge configurable de la sérialisation/déssérialisation que vous voudrez peut-être jeter un coup d'œil.

La bibliothèque prend en charge:

  • Python 2.7, 3.4, 3.5 et 3.6.
  • SQLAlchemy versions 0.9 et supérieures
  • sérialisation/dé-sérialisation vers/depuis JSON, CSV, YAML et Python dict
  • sérialisation/désérialisation des colonnes/attributs, relations, propriétés hybrides et proxy d'association
  • activation et désactivation de la sérialisation pour des formats particuliers et des colonnes/relations/attributs (par exemple, vous souhaitez prendre en charge une valeur inboundpassword, mais ne jamais inclure une valeur outbound)
  • traitement de valeur pré-sérialisation et post-désérialisation (pour validation ou contrainte de type)
  • une syntaxe assez simple, à la fois pythonique et parfaitement cohérente avec la propre approche de SQLAlchemy

Vous pouvez consulter la documentation complète (j'espère!) Ici: https://sqlathanor.readthedocs.io/en/latest

J'espère que cela t'aides!

2
Chris Modzelewski

Sérialisation et désérialisation personnalisées.

"from_json" (méthode de classe) construit un objet Model basé sur des données json.

"désérialiser" pourrait être appelé uniquement sur instance et fusionner toutes les données de json dans une instance de modèle.

"sérialiser" - sérialisation récursive

_WRITE_ONLY_property est nécessaire pour définir les propriétés d'écriture seule ("password_hash" par exemple).

class Serializable(object):
    __exclude__ = ('id',)
    __include__ = ()
    __write_only__ = ()

    @classmethod
    def from_json(cls, json, selfObj=None):
        if selfObj is None:
            self = cls()
        else:
            self = selfObj
        exclude = (cls.__exclude__ or ()) + Serializable.__exclude__
        include = cls.__include__ or ()
        if json:
            for prop, value in json.iteritems():
                # ignore all non user data, e.g. only
                if (not (prop in exclude) | (prop in include)) and isinstance(
                        getattr(cls, prop, None), QueryableAttribute):
                    setattr(self, prop, value)
        return self

    def deserialize(self, json):
        if not json:
            return None
        return self.__class__.from_json(json, selfObj=self)

    @classmethod
    def serialize_list(cls, object_list=[]):
        output = []
        for li in object_list:
            if isinstance(li, Serializable):
                output.append(li.serialize())
            else:
                output.append(li)
        return output

    def serialize(self, **kwargs):

        # init write only props
        if len(getattr(self.__class__, '__write_only__', ())) == 0:
            self.__class__.__write_only__ = ()
        dictionary = {}
        expand = kwargs.get('expand', ()) or ()
        prop = 'props'
        if expand:
            # expand all the fields
            for key in expand:
                getattr(self, key)
        iterable = self.__dict__.items()
        is_custom_property_set = False
        # include only properties passed as parameter
        if (prop in kwargs) and (kwargs.get(prop, None) is not None):
            is_custom_property_set = True
            iterable = kwargs.get(prop, None)
        # loop trough all accessible properties
        for key in iterable:
            accessor = key
            if isinstance(key, Tuple):
                accessor = key[0]
            if not (accessor in self.__class__.__write_only__) and not accessor.startswith('_'):
                # force select from db to be able get relationships
                if is_custom_property_set:
                    getattr(self, accessor, None)
                if isinstance(self.__dict__.get(accessor), list):
                    dictionary[accessor] = self.__class__.serialize_list(object_list=self.__dict__.get(accessor))
                # check if those properties are read only
                Elif isinstance(self.__dict__.get(accessor), Serializable):
                    dictionary[accessor] = self.__dict__.get(accessor).serialize()
                else:
                    dictionary[accessor] = self.__dict__.get(accessor)
        return dictionary
def alc2json(row):
    return dict([(col, str(getattr(row,col))) for col in row.__table__.columns.keys()])

Je pensais jouer un peu au golf de code avec celui-ci. 

FYI: J'utilise automap_base car nous avons un schéma conçu séparément en fonction des besoins de l'entreprise. Je viens tout juste de commencer à utiliser SQLAlchemy aujourd'hui, mais la documentation indique que automap_base est une extension de declarative_base, qui semble être le paradigme typique de SQLAlchemy ORM. Je pense donc que cela devrait fonctionner.

Il n’est pas intéressant de suivre les clés étrangères suivantes pour la solution de Tjorriemorrie , mais il fait simplement correspondre les colonnes à des valeurs et gère les types Python en str () - les valeurs de colonne. Nos valeurs sont constituées des résultats de type classe Python datetime.time et decimal.Decimal afin que le travail soit effectué.

J'espère que cela aide les passants!

1
hpatel71

le code suivant sérialisera le résultat de sqlalchemy en json.

import json
from collections import OrderedDict


def asdict(self):
    result = OrderedDict()
    for key in self.__mapper__.c.keys():
        if getattr(self, key) is not None:
            result[key] = str(getattr(self, key))
        else:
            result[key] = getattr(self, key)
    return result


def to_array(all_vendors):
    v = [ ven.asdict() for ven in all_vendors ]
    return json.dumps(v) 

Appeler amusant,

def all_products():
    all_products = Products.query.all()
    return to_array(all_products)
1
Chirag Vora

AlchemyEncoder est merveilleux mais échoue parfois avec les valeurs décimales. Voici un encodeur amélioré qui résout le problème décimal -

class AlchemyEncoder(json.JSONEncoder):
# To serialize SQLalchemy objects 
def default(self, obj):
    if isinstance(obj.__class__, DeclarativeMeta):
        model_fields = {}
        for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
            data = obj.__getattribute__(field)
            print data
            try:
                json.dumps(data)  # this will fail on non-encodable values, like other classes
                model_fields[field] = data
            except TypeError:
                model_fields[field] = None
        return model_fields
    if isinstance(obj, Decimal):
        return float(obj)
    return json.JSONEncoder.default(self, obj)
1
vineet agarwal

Utilisez le sérialiseur intégré dans SQLAlchemy:

from sqlalchemy.ext.serializer import loads, dumps
obj = MyAlchemyObject()
# serialize object
serialized_obj = dumps(obj)

# deserialize object
obj = loads(serialized_obj)

Si vous transférez l'objet entre les sessions, pensez à le détacher de la session en cours en utilisant session.expunge(obj). Pour le rattacher à nouveau, faites simplement session.add(obj).

0
chribsen

Sous Flask, cela fonctionne et gère les champs datatime, transformant un champ de type
'time': datetime.datetime(2018, 3, 22, 15, 40) dans
"time": "2018-03-22 15:40:00":

obj = {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}

# This to get the JSON body
return json.dumps(obj)

# Or this to get a response object
return jsonify(obj)
0
belvederef

Les inductances de sérialiseur intégrées avec utf-8 ne peuvent pas décoder l'octet de début non valide pour certaines entrées. Au lieu de cela, je suis allé avec:

def row_to_dict(row):
    temp = row.__dict__
    temp.pop('_sa_instance_state', None)
    return temp


def rows_to_list(rows):
    ret_rows = []
    for row in rows:
        ret_rows.append(row_to_dict(row))
    return ret_rows


@website_blueprint.route('/api/v1/some/endpoint', methods=['GET'])
def some_api():
    '''
    /some_endpoint
    '''
    rows = rows_to_list(SomeModel.query.all())
    response = app.response_class(
        response=jsonplus.dumps(rows),
        status=200,
        mimetype='application/json'
    )
    return response
0
RobotHumans

Python 3.7+ et Flask 1.1+ peuvent utiliser le package intégré dataclasses

from dataclasses import dataclass
from datetime import datetime
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
db = SQLAlchemy(app)


@dataclass
class User(db.Model):
  id: int
  email: str

  id = db.Column(db.Integer, primary_key=True, auto_increment=True)
  email = db.Column(db.String(200), unique=True)


@app.route('/users/')
def users():
  users = User.query.all()
  return jsonify(users)  


if __== "__main__":
  users = User(email="[email protected]"), User(email="[email protected]")
  db.create_all()
  db.session.add_all(users)
  db.session.commit()
  app.run()

La route /users/ renverra maintenant une liste d'utilisateurs.

[
  {"email": "[email protected]", "id": 1},
  {"email": "[email protected]", "id": 2}
]

Sérialiser automatiquement les modèles associés

@dataclass
class Account(db.Model):
  id: int
  users: User

  id = db.Column(db.Integer)
  users = db.relationship(User)  # User model would need a db.ForeignKey field

La réponse de jsonify(account) serait la suivante.

{  
   "id":1,
   "users":[  
      {  
         "email":"[email protected]",
         "id":1
      },
      {  
         "email":"[email protected]",
         "id":2
      }
   ]
}

Ecraser l'encodeur JSON par défaut

from flask.json import JSONEncoder


class CustomJSONEncoder(JSONEncoder):
  "Add support for serializing timedeltas"

  def default(o):
    if type(o) == datetime.timedelta:
      return str(o)
    else:
      return super().default(o)

app.json_encoder = CustomJSONEncoder      
0
tom

Je sais que c'est un article assez ancien. J'ai pris la solution donnée par @SashaB et modifiée selon mes besoins. 

J'ai ajouté les choses suivantes:

  1. Liste des champs ignorés: liste des champs à ignorer lors de la sérialisation
  2. Liste de remplacement de champ: Un dictionnaire contenant les noms de champs à remplacer par des valeurs lors de la sérialisation.
  3. Méthodes supprimées et baseQuery étant sérialisé

Mon code est le suivant:

def alchemy_json_encoder(revisit_self = False, fields_to_expand = [], fields_to_ignore = [], fields_to_replace = {}):
   """
   Serialize SQLAlchemy result into JSon
   :param revisit_self: True / False
   :param fields_to_expand: Fields which are to be expanded for including their children and all
   :param fields_to_ignore: Fields to be ignored while encoding
   :param fields_to_replace: Field keys to be replaced by values assigned in dictionary
   :return: Json serialized SQLAlchemy object
   """
   _visited_objs = []
   class AlchemyEncoder(json.JSONEncoder):
      def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # don't re-visit self
            if revisit_self:
                if obj in _visited_objs:
                    return None
                _visited_objs.append(obj)

            # go through each field in this SQLalchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and x not in fields_to_ignore]:
                val = obj.__getattribute__(field)
                # is this field method defination, or an SQLalchemy object
                if not hasattr(val, "__call__") and not isinstance(val, BaseQuery):
                    field_name = fields_to_replace[field] if field in fields_to_replace else field
                    # is this field another SQLalchemy object, or a list of SQLalchemy objects?
                    if isinstance(val.__class__, DeclarativeMeta) or \
                            (isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
                        # unless we're expanding this field, stop here
                        if field not in fields_to_expand:
                            # not expanding this field: set it to None and continue
                            fields[field_name] = None
                            continue

                    fields[field_name] = val
            # a json-encodable dict
            return fields

        return json.JSONEncoder.default(self, obj)
   return AlchemyEncoder

J'espère que ça aide quelqu'un!

0
srahul07