Comment sérialiser SqlAlchemy résultat JSON?
Django a quelques bonnes automatique de la sérialisation de l'ORM modèles retourné à partir de DB au format JSON.
Comment sérialiser SQLAlchemy résultat de la requête au format JSON?
J'ai essayé jsonpickle.encode
mais il code pour objet de requête elle-même.
J'ai essayé json.dumps(items)
mais il renvoie
TypeError: <Product('3', 'some name', 'some desc')> is not JSON serializable
Est-il vraiment si difficile de sérialiser SQLAlchemy ORM objets JSON /XML? N'est-ce pas là un défaut sérialiseur pour elle? Il est très fréquent que la tâche de sérialiser ORM résultats de la requête de nos jours.
Ce que j'ai besoin est juste de retour JSON ou XML de représentation des données de SQLAlchemy résultat de la requête.
SQLAlchemy objets du résultat de la requête en JSON/XML format est nécessaire pour être utilisé en javascript datagird (JQGrid http://www.trirand.com/blog/)
Vous devez vous connecter pour publier un commentaire.
Un plat de mise en œuvre de
Vous pouvez utiliser quelque chose comme ceci:
et ensuite de les convertir en JSON à l'aide de:
Il ignore les champs qui ne sont pas encodable (mis à 'None').
Il n'a pas d'auto-développer les relations (car cela pourrait l'amener à l'auto-références, et boucle pour toujours).
Récursive, non-circulaire de mise en œuvre de
Si, toutefois, vous préférez faire une boucle pour toujours, vous pouvez utiliser:
Puis coder les objets à l'aide de:
Ce serait de coder tous les enfants et tous leurs enfants, et tous leurs enfants... Potentiellement coder l'ensemble de votre base de données, dans le fond. Lorsqu'il atteint quelque chose de son encodé en avant, il va encoder comme "Aucun".
Récursive, peut-être-circulaire, la mise en œuvre sélective
Une autre solution, sans doute mieux, c'est d'être capable de spécifier les champs que vous souhaitez développer:
Vous pouvez maintenant appeler avec:
À seulement étendre SQLAlchemy champs appelés "parents", par exemple.
online_order
etaddress
, à la fois avec une relation àuser
, maisonline_order
a aussi une relation àaddress
. Si je voulais sérialiser tout cela, je dois inclureaddress
dans lefields_to_expand
, mais je ne veux pas de manière redondante sérialiseraddress
en raison de sa relation à la foisuser
etonline_order
.for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
de sorte qu'il estfor field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and not x.startswith('query')]:
. Gardez à l'esprit que cette solution va vous empêcher d'avoir une propriété/relation avec le nom "query"Vous pourriez juste à la sortie de votre objet comme dict:
Et puis vous utilisez de l'Utilisateur.as_dict() pour sérialiser l'objet.
Comme expliqué dans Convertir sqlalchemy ligne d'objet de python dict
JSONEncoder
objet. Vous pouvez sous-classe pour définir votre propre encodeur pour un objet quelconque, y compris de type datetime. Notez queFlask
, par exemple, le support de l'encodage datetime en JSON hors de la boîte (avec la dernière version).as_dict
sur eux, ou vous pouvez l'imaginer à l'aide deoperator.attrgetter
et d'être plus explicite à propos de tout. Il y a un moyen d'obtenir des relations sur un modèle en programmant ainsi.return {c.name: unicode(getattr(self, c.name)) for c in self.__table__.columns}
{a.key: rowproxy[a.class_attribute.name] for a in User.__mapper__.attrs}
Vous pouvez convertir un RowProxy à une dict comme ceci:
Puis sérialiser que JSON ( vous devrez spécifier un codeur pour des choses comme
datetime
valeurs )Il n'est pas difficile si vous voulez juste un enregistrement ( et non pas une hiérarchie complète des documents connexes ).
Je recommande d'utiliser un récent surface de la bibliothèque guimauve. Il permet de créer des sérialiseurs pour représenter votre instances de modèle avec support pour les relations et les objets imbriqués.
Ont un coup d'oeil à theier SQLAlchemy Exemple.
En Flacon De JsonTools paquet a une mise en œuvre de JsonSerializableBase de la classe de Base pour vos modèles.
Utilisation:
Maintenant la
User
modèle est magiquement serializable.Si votre cadre n'est pas le Flacon, vous pouvez simplement saisir le code
import flask.ext.whatever
est plus pris en charge dans le Flacon 1.0.Pour des raisons de sécurité, vous ne devriez jamais vous retourner tous les modèle de champs. Je préfère choisir de manière sélective entre eux.
Flacon de l'encodage json prend désormais en charge l'UUID, datetime et les relations (et ajouté
query
etquery_class
pour flask_sqlalchemydb.Model
classe). J'ai mis à jour le codeur comme suit:Avec ce que je peux éventuellement ajouter un
__json__
propriété qui retourne la liste des champs que je souhaite encoder:- Je ajouter @jsonapi à mon avis, le retour de la resultlist et puis mon résultat est comme suit:
@jsonapi
à@app.route
dans views.py, etc), mais j'aime la simplicité. Je pense que c'est bon marché Flacon ajouté datetime mais pas de date, donc j'ai ajouté moi-même pour json_encoder.py:value=...
^if isinstance(value, date):
^data[field] = datetime.combine(value, time.min).isoformat()
^else:
^try:...
Vous pouvez utiliser l'introspection de SqlAlchemy comme ceci :
S'inspirer de réponse ici :
Convertir sqlalchemy ligne d'objet de python dict
Une explication plus détaillée.
Dans votre modèle, ajouter:
La
str()
est pour python 3 donc, si à l'aide de python 2 utilisezunicode()
. Il devrait aider à désérialiser les dates. Vous pouvez le supprimer si pas de traiter avec ces.Désormais, vous pouvez interroger la base de données comme ceci
First()
est nécessaire pour éviter les erreurs étranges.as_dict()
maintenant désérialiser le résultat. Après la désérialisation, il est prêt à être transformé en jsonIl n'est pas si compliqué. J'ai écrit du code pour ce faire. Je travaille toujours sur elle, et il utilise le MochiKit cadre. Essentiellement, il se traduit par des objets composés entre Python et Javascript à l'aide d'un proxy et enregistré JSON convertisseurs.
Navigateur de côté pour les objets de base de données est db.js
Il a besoin de la base de Python proxy source dans proxy.js.
Sur le Python côté, il y a la base module de proxy.
Puis, enfin, la SqlAlchemy objet de l'encodeur dans webserver.py.
Elle dépend aussi de métadonnées extracteurs trouvé dans les models.py fichier.
Personnalisé de sérialisation et de désérialisation.
"from_json" (méthode de classe) construit un objet de Modèle basé sur les données json.
"désérialiser" pourrait être appelé que sur l'exemple, et la fusion de toutes les données json en instance du Modèle.
"sérialiser" - récursive de sérialisation
__write_seulement__ de la propriété est nécessaire pour définir écrire uniquement les propriétés ("password_hash" par exemple).
Voici une solution qui vous permet de sélectionner les relations que vous souhaitez inclure dans votre sortie aussi profond que vous voulez aller.
NOTE: Ceci est une réécriture complète de prendre un dict/str comme un arg, plutôt qu'une liste. corrige quelques trucs..
donc, pour un exemple d'utilisation de la personne/famille/maisons/chambres... transformant en json tous vous avez besoin est
Alors que la question d'origine remonte à un certain temps, le nombre de réponses ici (et mes propres expériences) suggèrent que c'est un non-trivial question avec beaucoup de différentes approches de complexité variable avec différents arbitrages.
C'est pourquoi j'ai construit le SQLAthanor de la bibliothèque qui s'étend de SQLAlchemy déclaratif de l'ORM, avec plage de sérialisation/dé-sérialisation de soutien que vous voudrez peut-être jeter un oeil à.
La bibliothèque prend en charge:
dict
password
valeur, mais ne jamais inclure un sortant un)Vous pouvez vérifier l' (j'espère!) complet docs ici: https://sqlathanor.readthedocs.io/en/latest
Espérons que cette aide!
Je pensais jouer un peu de code de golf avec celui-ci.
Pour info: je suis en utilisant automap_base depuis que nous avons conçus séparément schéma en fonction des exigences de l'entreprise. J'ai juste commencé à l'aide de SQLAlchemy aujourd'hui, mais la documentation indique que les automap_base est une extension pour declarative_base qui semble être typique de paradigme dans la SQLAlchemy ORM je crois que cela devrait fonctionner.
Il n'a pas obtenir la fantaisie avec des clés étrangères par Tjorriemorrie's solution, mais il a simplement fait correspondre les colonnes de valeurs et de poignées de Python de type str()-ing les valeurs de la colonne. Nos valeurs sont Python datetime.le temps et les décimales.Classe Decimal type de résultats, il fait le travail.
Espère que cela aide à tous les passants!
code suivant va sérialiser sqlalchemy résultat json.
L'appel de plaisir,
La AlchemyEncoder est merveilleux, mais échoue parfois avec des valeurs Décimales. Voici une amélioration de l'encodeur qui résout le décimal problème -
Je sais que c'est tout à fait un vieux poste. J'ai pris la solution donnée par @SashaB et modifié selon mon besoin.
J'ai ajouté, à la suite des choses:
Mon code est comme suit:
Espère que cela aide quelqu'un!
Utiliser le construit-dans sérialiseur dans SQLAlchemy:
Si vous êtes le transfert de l'objet entre les sessions, n'oubliez pas de détacher l'objet à partir de la session en cours à l'aide de
session.expunge(obj)
.Pour l'attacher à nouveau, il suffit de faire
session.add(obj)
.En vertu de la Fiole, cela fonctionne et poignées datatime champs, la transformation d'un champ de type
'time': datetime.datetime(2018, 3, 22, 15, 40)
en"time": "2018-03-22 15:40:00"
:Construit dans le sérialiseur étouffe avec de l'utf-8 ne peut pas décoder invalide octet de départ pour certains intrants. Au lieu de cela, je suis allé avec:
De mon point de vue en utilisant (trop nombreux?) dictionnaires:
Cours d'exécution à flasque (y compris jsonify) et flask_sqlalchemy pour imprimer des sorties sous forme de JSON.
Appeler la fonction avec jsonify(serialize()).
Fonctionne avec tous les SQLAlchemy requêtes que j'ai essayé jusqu'à présent (en cours d'exécution SQLite3)