Je cherche depuis pas mal de temps sans succès. Mon projet n'utilise pas Django, existe-t-il un moyen simple de sérialiser les modèles App Engine (google.appengine.ext.db.Model) en JSON ou dois-je écrire mon propre sérialiseur?
Modèle:
class Photo(db.Model):
filename = db.StringProperty()
title = db.StringProperty()
description = db.StringProperty(multiline=True)
date_taken = db.DateTimeProperty()
date_uploaded = db.DateTimeProperty(auto_now_add=True)
album = db.ReferenceProperty(Album, collection_name='photo')
python
json
google-app-engine
user111677
la source
la source
json.dumps(db.to_dict(Photo))
C'est la solution la plus simple que j'ai trouvée. Il ne nécessite que 3 lignes de codes.
Ajoutez simplement une méthode à votre modèle pour renvoyer un dictionnaire:
class DictModel(db.Model): def to_dict(self): return dict([(p, unicode(getattr(self, p))) for p in self.properties()])
SimpleJSON fonctionne désormais correctement:
class Photo(DictModel): filename = db.StringProperty() title = db.StringProperty() description = db.StringProperty(multiline=True) date_taken = db.DateTimeProperty() date_uploaded = db.DateTimeProperty(auto_now_add=True) album = db.ReferenceProperty(Album, collection_name='photo') from django.utils import simplejson from google.appengine.ext import webapp class PhotoHandler(webapp.RequestHandler): def get(self): photos = Photo.all() self.response.out.write(simplejson.dumps([p.to_dict() for p in photos]))
la source
Dans la dernière version (1.5.2) du SDK App Engine, une
to_dict()
fonction qui convertit les instances de modèle en dictionnaires a été introduite dansdb.py
. Voir les notes de version .Il n'y a pas encore de référence à cette fonction dans la documentation, mais je l'ai essayé moi-même et cela fonctionne comme prévu.
la source
AttributeError: 'module' object has no attribute 'to_dict'
quand jefrom google.appengine.ext import db
et l' utilisationsimplejson.dumps(db.to_dict(r))
(où r est une instance d'une sous - classe db.Model). Je ne vois pas "to_dict" dans google_appengine / google / appengine / ext / db / *Pour sérialiser des modèles, ajoutez un encodeur json personnalisé comme dans le python suivant:
import datetime from google.appengine.api import users from google.appengine.ext import db from django.utils import simplejson class jsonEncoder(simplejson.JSONEncoder): def default(self, obj): if isinstance(obj, datetime.datetime): return obj.isoformat() elif isinstance(obj, db.Model): return dict((p, getattr(obj, p)) for p in obj.properties()) elif isinstance(obj, users.User): return obj.email() else: return simplejson.JSONEncoder.default(self, obj) # use the encoder as: simplejson.dumps(model, cls=jsonEncoder)
Cela encodera:
Pour décoder la date, vous pouvez utiliser ce javascript:
function decodeJsonDate(s){ return new Date( s.slice(0,19).replace('T',' ') + ' GMT' ); } // Note that this function truncates milliseconds.
Remarque: Merci à l'utilisateur pydave qui a édité ce code pour le rendre plus lisible. J'avais initialement utilisé les expressions if / else de python pour exprimer
jsonEncoder
en moins de lignes comme suit: (J'ai ajouté quelques commentaires et utiliségoogle.appengine.ext.db.to_dict
, pour le rendre plus clair que l'original.)class jsonEncoder(simplejson.JSONEncoder): def default(self, obj): isa=lambda x: isinstance(obj, x) # isa(<type>)==True if obj is of type <type> return obj.isoformat() if isa(datetime.datetime) else \ db.to_dict(obj) if isa(db.Model) else \ obj.email() if isa(users.User) else \ simplejson.JSONEncoder.default(self, obj)
la source
Vous n'avez pas besoin d'écrire votre propre "analyseur" (un analyseur transforme vraisemblablement JSON en objet Python), mais vous pouvez toujours sérialiser votre objet Python vous-même.
En utilisant simplejson :
import simplejson as json serialized = json.dumps({ 'filename': self.filename, 'title': self.title, 'date_taken': date_taken.isoformat(), # etc. })
la source
Pour les cas simples, j'aime l'approche préconisée ici à la fin de l'article:
# after obtaining a list of entities in some way, e.g.: user = users.get_current_user().email().lower(); col = models.Entity.gql('WHERE user=:1',user).fetch(300, 0) # ...you can make a json serialization of name/key pairs as follows: json = simplejson.dumps(col, default=lambda o: {o.name :str(o.key())})
L'article contient également, à l'autre bout du spectre, une classe de sérialiseur complexe qui enrichit ceux de django (et ne nécessite
_meta
pas - je ne sais pas pourquoi vous obtenez des erreurs sur _meta manquant, peut-être le bogue décrit ici ) avec la possibilité de sérialiser calculé propriétés / méthodes. La plupart du temps, vos besoins de sérialisation se situent quelque part entre les deux, et pour ceux-ci, une approche introspective telle que celle de @David Wilson peut être préférable.la source
Même si vous n'utilisez pas django comme framework, ces bibliothèques sont toujours à votre disposition.
from django.core import serializers data = serializers.serialize("xml", Photo.objects.all())
la source
Si vous utilisez app-engine-patch, il déclarera automatiquement l'
_meta
attribut pour vous, puis vous pourrez utiliserdjango.core.serializers
comme vous le feriez normalement sur les modèles django (comme dans le code de sledge).App-engine-patch a quelques autres fonctionnalités intéressantes telles qu'une authentification hybride (comptes django + google) et la partie admin de django fonctionne.
la source
La réponse de Mtgred ci-dessus a fonctionné à merveille pour moi - je l'ai légèrement modifiée pour que je puisse également obtenir la clé de l'entrée. Pas aussi peu de lignes de code, mais cela me donne la clé unique:
class DictModel(db.Model): def to_dict(self): tempdict1 = dict([(p, unicode(getattr(self, p))) for p in self.properties()]) tempdict2 = {'key':unicode(self.key())} tempdict1.update(tempdict2) return tempdict1
la source
J'ai étendu la classe JSON Encoder écrite par dpatru pour prendre en charge:
Propriétés de filtrage - seules les propriétés avec un
verbose_name
seront encodées en JSONclass DBModelJSONEncoder(json.JSONEncoder): """Encodes a db.Model into JSON""" def default(self, obj): if (isinstance(obj, db.Query)): # It's a reference query (holding several model instances) return [self.default(item) for item in obj] elif (isinstance(obj, db.Model)): # Only properties with a verbose name will be displayed in the JSON output properties = obj.properties() filtered_properties = filter(lambda p: properties[p].verbose_name != None, properties) # Turn each property of the DB model into a JSON-serializeable entity json_dict = dict([( p, getattr(obj, p) if (not isinstance(getattr(obj, p), db.Model)) else self.default(getattr(obj, p)) # A referenced model property ) for p in filtered_properties]) json_dict['id'] = obj.key().id() # Add the model instance's ID (optional - delete this if you do not use it) return json_dict else: # Use original JSON encoding return json.JSONEncoder.default(self, obj)
la source
Comme mentionné par https://stackoverflow.com/users/806432/fredva , le to_dict fonctionne très bien. Voici mon code que j'utilise.
foos = query.fetch(10) prepJson = [] for f in foos: prepJson.append(db.to_dict(f)) myJson = json.dumps(prepJson))
la source
Il existe une méthode, "Model.properties ()", définie pour toutes les classes Model. Il renvoie le dict que vous recherchez.
from django.utils import simplejson class Photo(db.Model): # ... my_photo = Photo(...) simplejson.dumps(my_photo.properties())
Voir Propriétés du modèle dans la documentation.
la source
TypeError: <google.appengine.ext.db.StringProperty object at 0x4694550> is not JSON serializable
Ces API (google.appengine.ext.db) ne sont plus recommandées. Les applications qui utilisent ces API ne peuvent s'exécuter que dans l'environnement d'exécution App Engine Python 2 et devront migrer vers d'autres API et services avant de migrer vers l'environnement d'exécution App Engine Python 3. Pour en savoir plus: cliquez ici
la source
Pour sérialiser une instance de modèle Datastore, vous ne pouvez pas utiliser json.dumps (pas testé mais Lorenzo l'a signalé). Peut-être qu'à l'avenir, ce qui suit fonctionnera.
http://docs.python.org/2/library/json.html
import json string = json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}]) object = json.loads(self.request.body)
la source