Saya telah mencari cukup lama tanpa hasil. Proyek saya tidak menggunakan Django, apakah ada cara sederhana untuk membuat serial model App Engine (google.appengine.ext.db.Model) menjadi JSON atau apakah saya perlu menulis serializer saya sendiri?
Model:
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
pengguna111677
sumber
sumber
json.dumps(db.to_dict(Photo))
Ini adalah solusi paling sederhana yang saya temukan. Ini hanya membutuhkan 3 baris kode.
Cukup tambahkan metode ke model Anda untuk mengembalikan kamus:
class DictModel(db.Model): def to_dict(self): return dict([(p, unicode(getattr(self, p))) for p in self.properties()])
SimpleJSON sekarang berfungsi dengan baik:
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]))
sumber
Dalam rilis terbaru (1.5.2) dari App Engine SDK,
to_dict()
fungsi yang mengonversi instance model menjadi kamus diperkenalkan didb.py
. Lihat catatan rilis .Belum ada referensi ke fungsi ini dalam dokumentasi, tetapi saya telah mencobanya sendiri dan berfungsi seperti yang diharapkan.
sumber
AttributeError: 'module' object has no attribute 'to_dict'
ketika sayafrom google.appengine.ext import db
dan menggunakansimplejson.dumps(db.to_dict(r))
(di mana r adalah turunan dari subkelas db.Model). Saya tidak melihat "to_dict" di google_appengine / google / appengine / ext / db / *Untuk membuat model berseri, tambahkan encoder json kustom seperti pada python berikut:
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)
Ini akan menyandikan:
Untuk memecahkan kode tanggal Anda dapat menggunakan javascript ini:
function decodeJsonDate(s){ return new Date( s.slice(0,19).replace('T',' ') + ' GMT' ); } // Note that this function truncates milliseconds.
Catatan: Terima kasih kepada pengguna pydave yang telah mengedit kode ini agar lebih mudah dibaca. Saya awalnya menggunakan ekspresi if / else python untuk diekspresikan
jsonEncoder
dalam lebih sedikit baris sebagai berikut: (Saya telah menambahkan beberapa komentar dan menggunakangoogle.appengine.ext.db.to_dict
, untuk membuatnya lebih jelas daripada aslinya.)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)
sumber
Anda tidak perlu menulis "parser" Anda sendiri (pengurai mungkin akan mengubah JSON menjadi objek Python), tetapi Anda masih bisa membuat serialisasi objek Python Anda sendiri.
Menggunakan simplejson :
import simplejson as json serialized = json.dumps({ 'filename': self.filename, 'title': self.title, 'date_taken': date_taken.isoformat(), # etc. })
sumber
Untuk kasus sederhana, saya menyukai pendekatan yang dianjurkan di sini di akhir artikel:
# 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())})
Artikel ini juga berisi, di ujung lain spektrum, kelas serializer kompleks yang memperkaya django (dan memang membutuhkan
_meta
- tidak yakin mengapa Anda mendapatkan kesalahan tentang _meta hilang, mungkin bug yang dijelaskan di sini ) dengan kemampuan untuk membuat serial yang dihitung properti / metode. Sebagian besar waktu yang Anda butuhkan serialisasi terletak di antara keduanya, dan bagi mereka pendekatan introspektif seperti @David Wilson's mungkin lebih disukai.sumber
Bahkan jika Anda tidak menggunakan django sebagai kerangka kerja, pustaka tersebut masih tersedia untuk Anda gunakan.
from django.core import serializers data = serializers.serialize("xml", Photo.objects.all())
sumber
Jika Anda menggunakan app-engine-patch, itu akan secara otomatis mendeklarasikan
_meta
atribut untuk Anda, dan kemudian Anda dapat menggunakannyadjango.core.serializers
seperti yang biasa Anda lakukan pada model django (seperti dalam kode sledge).App-engine-patch memiliki beberapa fitur keren lainnya seperti otentikasi hybrid (akun django + google), dan bagian admin dari django berfungsi.
sumber
Jawaban Mtgred di atas bekerja dengan sangat baik bagi saya - saya sedikit memodifikasinya sehingga saya juga bisa mendapatkan kunci untuk entri tersebut. Tidak sesedikit baris kode, tetapi memberi saya kunci unik:
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
sumber
Saya telah memperluas kelas JSON Encoder yang ditulis oleh dpatru untuk mendukung:
Properti pemfilteran - hanya properti dengan a yang
verbose_name
akan dikodekan ke dalam 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)
sumber
Seperti yang disebutkan oleh https://stackoverflow.com/users/806432/fredva , to_dict berfungsi dengan baik. Ini kode yang saya gunakan.
foos = query.fetch(10) prepJson = [] for f in foos: prepJson.append(db.to_dict(f)) myJson = json.dumps(prepJson))
sumber
Ada metode, "Model.properties ()", yang ditentukan untuk semua kelas Model. Ini mengembalikan perintah yang Anda cari.
from django.utils import simplejson class Photo(db.Model): # ... my_photo = Photo(...) simplejson.dumps(my_photo.properties())
Lihat Properti model di dokumen.
sumber
TypeError: <google.appengine.ext.db.StringProperty object at 0x4694550> is not JSON serializable
API ini (google.appengine.ext.db) tidak lagi direkomendasikan. Aplikasi yang menggunakan API ini hanya dapat berjalan di runtime App Engine Python 2 dan perlu bermigrasi ke API dan layanan lain sebelum bermigrasi ke runtime App Engine Python 3. Untuk mengetahui lebih lanjut: klik di sini
sumber
Untuk membuat serial instance Model Datastore, Anda tidak dapat menggunakan json.dumps (belum diuji tetapi Lorenzo menunjukkannya). Mungkin di masa depan yang berikut ini akan berhasil.
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)
sumber