Я долго искал безуспешно. В моем проекте не используется Django. Есть ли простой способ сериализации моделей App Engine (google.appengine.ext.db.Model) в JSON или мне нужно написать собственный сериализатор?
Модель:
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
источник
источник
json.dumps(db.to_dict(Photo))
Это самое простое решение, которое я нашел. Требуется всего 3 строки кода.
Просто добавьте в модель метод для возврата словаря:
class DictModel(db.Model): def to_dict(self): return dict([(p, unicode(getattr(self, p))) for p in self.properties()])
SimpleJSON теперь работает правильно:
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]))
источник
В последнем (1.5.2) выпуске App Engine SDK
to_dict()
функция преобразования экземпляров модели в словари была представлена вdb.py
. См. Примечания к выпуску .В документации пока нет ссылки на эту функцию, но я попробовал ее сам, и она работает должным образом.
источник
AttributeError: 'module' object has no attribute 'to_dict'
когдаfrom google.appengine.ext import db
и используюsimplejson.dumps(db.to_dict(r))
(где r - экземпляр подкласса db.Model). Я не вижу «to_dict» в google_appengine / google / appengine / ext / db / *Чтобы сериализовать модели, добавьте пользовательский кодировщик json, как в следующем питоне:
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)
Это закодирует:
Чтобы расшифровать дату, вы можете использовать этот javascript:
function decodeJsonDate(s){ return new Date( s.slice(0,19).replace('T',' ') + ' GMT' ); } // Note that this function truncates milliseconds.
Примечание. Спасибо пользователю pydave, который отредактировал этот код, чтобы сделать его более читабельным. Изначально я использовал выражения if / else в Python для выражения
jsonEncoder
меньшего количества строк следующим образом: (Я добавил несколько комментариев и использовал ихgoogle.appengine.ext.db.to_dict
, чтобы сделать его более понятным, чем оригинал.)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)
источник
Вам не нужно писать собственный «синтаксический анализатор» (синтаксический анализатор предположительно превратит JSON в объект Python), но вы все равно можете сериализовать свой объект Python самостоятельно.
Используя simplejson :
import simplejson as json serialized = json.dumps({ 'filename': self.filename, 'title': self.title, 'date_taken': date_taken.isoformat(), # etc. })
источник
В простых случаях мне нравится подход, который предлагается здесь, в конце статьи:
# 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())})
В статье также содержится, на другом конце спектра, сложный класс сериализатора, который обогащает django (и требует
_meta
- не уверен, почему вы получаете ошибки об отсутствии _meta, возможно, об ошибке, описанной здесь ) с возможностью сериализации вычисленных свойства / методы. В большинстве случаев сериализация находится где-то посередине, и для них может быть предпочтительнее интроспективный подход, такой как @David Wilson.источник
Даже если вы не используете django в качестве фреймворка, эти библиотеки все еще доступны для вас.
from django.core import serializers data = serializers.serialize("xml", Photo.objects.all())
источник
Если вы используете app-engine-patch, он автоматически объявляет
_meta
атрибут для вас, а затем вы можете использовать,django.core.serializers
как обычно, на моделях django (как в коде sledge).App-engine-patch имеет некоторые другие интересные функции, такие как гибридная аутентификация (учетные записи django + google), а также работает административная часть django.
источник
Ответ Mtgred выше отлично сработал для меня - я немного изменил его, чтобы я мог также получить ключ для входа. Не как несколько строк кода, но он дает мне уникальный ключ:
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
источник
Я расширил класс JSON Encoder, написанный dpatru, для поддержки:
Фильтрация свойств -
verbose_name
в JSON будут кодироваться только свойства с символом a.class 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)
источник
Как упоминалось в https://stackoverflow.com/users/806432/fredva , to_dict отлично работает. Вот мой код, который я использую.
foos = query.fetch(10) prepJson = [] for f in foos: prepJson.append(db.to_dict(f)) myJson = json.dumps(prepJson))
источник
Существует метод Model.properties (), определенный для всех классов модели. Он возвращает искомый словарь.
from django.utils import simplejson class Photo(db.Model): # ... my_photo = Photo(...) simplejson.dumps(my_photo.properties())
См. Свойства модели в документации.
источник
TypeError: <google.appengine.ext.db.StringProperty object at 0x4694550> is not JSON serializable
Эти API (google.appengine.ext.db) больше не рекомендуются. Приложения, использующие эти API-интерфейсы, могут работать только в среде выполнения Python 2 в App Engine, и перед переходом в среду выполнения Python 3 для App Engine необходимо будет перейти на другие API и службы. Чтобы узнать больше: нажмите здесь
источник
Чтобы сериализовать экземпляр модели хранилища данных, вы не можете использовать json.dumps (не тестировал, но Лоренцо указал на это). Возможно, в будущем сработает следующее.
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)
источник