如何将db.model对象序列化为json?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (14)

使用时

from django.utils import simplejson

在从db.Model它派生的类型的对象上抛出异常。如何绕过这个?

提问于
用户回答回答于

删除编码方法,因为它包含循环引用。调整后的类应如下所示:

import datetime  
import time 

from google.appengine.api import users 
from google.appengine.ext import db 
from django.utils import simplejson  


class GqlEncoder(simplejson.JSONEncoder): 

    """Extends JSONEncoder to add support for GQL results and properties. 

    Adds support to simplejson JSONEncoders for GQL results and properties by 
    overriding JSONEncoder's default method. 
    """ 

    # TODO Improve coverage for all of App Engine's Property types. 

    def default(self, obj): 

        """Tests the input object, obj, to encode as JSON.""" 

        if hasattr(obj, '__json__'): 
            return getattr(obj, '__json__')() 

        if isinstance(obj, db.GqlQuery): 
            return list(obj) 

        elif isinstance(obj, db.Model): 
            properties = obj.properties().items() 
            output = {} 
            for field, value in properties: 
                output[field] = getattr(obj, field) 
            return output 

        elif isinstance(obj, datetime.datetime): 
            output = {} 
            fields = ['day', 'hour', 'microsecond', 'minute', 'month', 'second', 'year'] 
            methods = ['ctime', 'isocalendar', 'isoformat', 'isoweekday', 'timetuple'] 
            for field in fields: 
                output[field] = getattr(obj, field) 
            for method in methods: 
                output[method] = getattr(obj, method)() 
            output['epoch'] = time.mktime(obj.timetuple()) 
            return output

        elif isinstance(obj, datetime.date): 
            output = {} 
            fields = ['year', 'month', 'day'] 
            methods = ['ctime', 'isocalendar', 'isoformat', 'isoweekday', 'timetuple'] 
            for field in fields: 
                output[field] = getattr(obj, field) 
            for method in methods: 
                output[method] = getattr(obj, method)() 
            output['epoch'] = time.mktime(obj.timetuple()) 
            return output 

        elif isinstance(obj, time.struct_time): 
            return list(obj) 

        elif isinstance(obj, users.User): 
            output = {} 
            methods = ['nickname', 'email', 'auth_domain'] 
            for method in methods: 
                output[method] = getattr(obj, method)() 
            return output 

        return simplejson.JSONEncoder.default(self, obj) 

正如我将这个类保存在一个名为utils.py的文件中,并在适当的时候使用它导入它

import utils

然后我只是调用utils.GqlEncoder()。encode(结果),例如:

query = User.all()
results = query.fetch(10)

self.response.headers['Content-Type'] = "text/plain" # Alt. application/json
self.response.out.write( utils.GqlEncoder().encode(results) )

结果应该看起来像这样(我已经添加了一些换行以便更容易阅读):

[
{"date": {"ctime": "Tue Feb 23 10:41:21 2010", "hour": 10, "isoweekday": 2, "month": 2, 
        "second": 21, "microsecond": 495535, "isocalendar": [2010, 8, 2], "timetuple": [2010, 2, 23, 10, 41, 21, 1, 54, -1], 
        "year": 2010, "epoch": 1266921681.0, "isoformat": "2010-02-23T10:41:21.495535", "day": 23, "minute": 41}, 
"claimed_id": "https:\/\/www.google.com\/accounts\/o8\/id?id=abcdefghijklmnopqrstuvxyz", 
"display_name": "Alfred E Neumann", 
"email": null, 
"full_name": "Alfred E Neumann"
}, 
{"date": {"ctime": "Tue Feb 23 11:00:54 2010", "hour": 11, "isoweekday": 2, "month": 2, 
        "second": 54, "microsecond": 805261, "isocalendar": [2010, 8, 2], "timetuple": [2010, 2, 23, 11, 0, 54, 1, 54, -1], 
        "year": 2010, "epoch": 1266922854.0, "isoformat": "2010-02-23T11:00:54.805261", "day": 23, "minute": 0}, 
"claimed_id": "http:\/\/openid.domain.net\/john", 
"display_name": "", 
"email": "jp@domain.net", 
"full_name": "John Parnefjord"
}
]
用户回答回答于

添加此无用类http://code.google.com/p/google-app-engine-samples/source/browse/trunk/geochat/json.py?r=55

 import datetime  
 import time 

 from google.appengine.api import users 
 from google.appengine.ext import db 

#this is a mod on the orinal file for some reason it includes its own simplejson files i have ref django!
 from django.utils import simplejson  

 class GqlEncoder(simplejson.JSONEncoder): 

   """Extends JSONEncoder to add support for GQL results and properties. 

   Adds support to simplejson JSONEncoders for GQL results and properties by 
   overriding JSONEncoder's default method. 
   """ 

   # TODO Improve coverage for all of App Engine's Property types. 

   def default(self, obj): 

     """Tests the input object, obj, to encode as JSON.""" 

     if hasattr(obj, '__json__'): 
       return getattr(obj, '__json__')() 

     if isinstance(obj, db.GqlQuery): 
       return list(obj) 

     elif isinstance(obj, db.Model): 
       properties = obj.properties().items() 
       output = {} 
       for field, value in properties: 
         output[field] = getattr(obj, field) 
       return output 

     elif isinstance(obj, datetime.datetime): 
       output = {} 
       fields = ['day', 'hour', 'microsecond', 'minute', 'month', 'second', 
           'year'] 
       methods = ['ctime', 'isocalendar', 'isoformat', 'isoweekday', 
           'timetuple'] 
       for field in fields: 
         output[field] = getattr(obj, field) 
       for method in methods: 
         output[method] = getattr(obj, method)() 
       output['epoch'] = time.mktime(obj.timetuple()) 
       return output 

     elif isinstance(obj, time.struct_time): 
       return list(obj) 

     elif isinstance(obj, users.User): 
       output = {} 
       methods = ['nickname', 'email', 'auth_domain'] 
       for method in methods: 
         output[method] = getattr(obj, method)() 
       return output 

     return simplejson.JSONEncoder.default(self, obj) 


 def encode(input): 
   """Encode an input GQL object as JSON 

     Args: 
       input: A GQL object or DB property. 

     Returns: 
       A JSON string based on the input object.  

     Raises: 
       TypeError: Typically occurs when an input object contains an unsupported 
         type. 
     """ 
   return GqlEncoder().encode(input)   

保存为json.py

使用

import cgi
import os
import json 

from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db


class Greeting(db.Model):
    author = db.UserProperty()
    content = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)

class MainPage(webapp.RequestHandler):
    def get(self):
        greetings_query = Greeting.all().order('-date')
        greetings = greetings_query.fetch(5)

        if users.get_current_user():
            url = users.create_logout_url(self.request.uri)
            url_linktext = 'Logout'
        else:
            url = users.create_login_url(self.request.uri)
            url_linktext = 'Login'

        template_values = {
            'greetings': greetings,
            'url': url,
            'url_linktext': url_linktext,
            }

        path = os.path.join(os.path.dirname(__file__), 'index.html')
        self.response.out.write(template.render(path, template_values))


class Guestbook(webapp.RequestHandler):
    def post(self):
        greeting = Greeting()

        if users.get_current_user():
            greeting.author = users.get_current_user()

        greeting.content = self.request.get('content')
        greeting.put()
        self.redirect('/')



#here i return my json feed - simple implementaion for example
class FeedHandler(webapp.RequestHandler):

  def get(self):
    """Retrieve a feed"""
    user = None

    greetings_query = Greeting.all().order('-date')
    rs= greetings_query.fetch(5)
#this is the part that calls the encoder - dosnt cause an exception
    data = json.encode(rs)



#roll out to browser -might need to check my headers etc
    self.response.headers['Content-Type'] = 'application/json; charset=utf-8'  
    self.response.out.write(data)




application = webapp.WSGIApplication(
                                       [
                                       ('/', MainPage),
                                       ('/sign',Guestbook),
                                       ('/feed',FeedHandler),
                                       ], debug=True
                                    )

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

这是浏览器的回应:

[{"content": "", "date": {"ctime": "Sat Jan 23 02:40:22 2010", "hour": 2, "isoweekday": 6, "month": 1, "second": 22, "microsecond": 434000, "isocalendar": [2010, 3, 6], "timetuple": [2010, 1, 23, 2, 40, 22, 5, 23, -1], "year": 2010, "epoch": 1264214422.0, "isoformat": "2010-01-23T02:40:22.434000", "day": 23, "minute": 40}, "author": {"nickname": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "", "date": {"ctime": "Sat Jan 23 01:12:43 2010", "hour": 1, "isoweekday": 6, "month": 1, "second": 43, "microsecond": 972000, "isocalendar": [2010, 3, 6], "timetuple": [2010, 1, 23, 1, 12, 43, 5, 23, -1], "year": 2010, "epoch": 1264209163.0, "isoformat": "2010-01-23T01:12:43.972000", "day": 23, "minute": 12}, "author": {"nickname": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "test", "date": {"ctime": "Fri Jan 22 22:32:13 2010", "hour": 22, "isoweekday": 5, "month": 1, "second": 13, "microsecond": 659000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 32, 13, 4, 22, -1], "year": 2010, "epoch": 1264199533.0, "isoformat": "2010-01-22T22:32:13.659000", "day": 22, "minute": 32}, "author": {"nickname": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "", "date": {"ctime": "Fri Jan 22 22:29:49 2010", "hour": 22, "isoweekday": 5, "month": 1, "second": 49, "microsecond": 358000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 49, 4, 22, -1], "year": 2010, "epoch": 1264199389.0, "isoformat": "2010-01-22T22:29:49.358000", "day": 22, "minute": 29}, "author": {"nickname": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}, {"content": "ah it works!\r\n", "date": {"ctime": "Fri Jan 22 22:29:22 2010", "hour": 22, "isoweekday": 5, "month": 1, "second": 22, "microsecond": 995000, "isocalendar": [2010, 3, 5], "timetuple": [2010, 1, 22, 22, 29, 22, 4, 22, -1], "year": 2010, "epoch": 1264199362.0, "isoformat": "2010-01-22T22:29:22.995000", "day": 22, "minute": 29}, "author": {"nickname": "test@example.com", "email": "test@example.com", "auth_domain": "gmail.com"}}]

扫码关注云+社区