2010-01-22 28 views

Trả lời

0

Vì tôi không thể tìm thấy một giải pháp thích hợp, tôi đã viết của riêng tôi, mà không phải là chính xác một serializer JSON, nhưng một serializer Javascript

from google.appengine.ext import db 
from google.appengine.api.datastore_types import * 

def dumpStr(obj): 
    return "'" + obj + "'" 

def dumps(obj): 
    if isinstance(obj, str): 
     return dumpStr(obj) 
    elif obj == None: 
     return None 
    elif isinstance(obj, list): 
     items = []; 
     for item in obj: 
      items.append(dumps(item)) 
     return '[' + ','.join(items) + ']' 
    elif isinstance(obj, datetime.datetime): 
     return "new Date('%s')" % obj.ctime() 
    properties = []; 
    for property in dir(obj): 
     if property[0] != '_': 
      value = obj.__getattribute__(property) 
      valueClass = str(value.__class__) 
      if not(('function' in valueClass) or ('built' in valueClass) or ('method' in valueClass)): 
       value = dumps(value) 
       if value != None: 
        properties.append("'" + property + "':" + value) 
    if len(properties) == 0: 
     return str(obj) 
    else: 
     return '{' + ','.join(properties) + '}' 
+1

Chỉ là một cảnh báo: điều này sẽ * không * tạo JSON hợp lệ cho tất cả các đầu vào. Ví dụ: nếu một chuỗi chứa ''' hoặc '\ n' thì JSON sẽ không hợp lệ hoặc nếu obj chứa một số. Vì vậy, ** không sử dụng ** này - sử dụng câu trả lời được bình chọn hàng đầu. –

3

Không thể sử dụng json để sắp xếp bất kỳ thứ gì ngoài các loại cơ bản như dicts, danh sách, ints/longs và strings (đây không phải là toàn diện). Ví dụ, ngay cả những lệnh đơn giản không làm việc:

import json 
json.dumps(object()) 

Nếu bạn muốn serialize đối tượng django, bạn nên tham khảo các django documentation on serialization, mà sẽ sử dụng thư viện riêng của họ, nhưng họ làm làm hỗ trợ json.

+0

Nhân tiện, thư viện json được bao gồm trong Python 2.6 có chức năng tương đương với simplejson. – BrainCore

+2

Tôi khá chắc chắn Jader có nghĩa là appengine db.Model đối tượng, không phải là những django. –

+0

nó sẽ không hoạt động với Google App Engine 'db.Model', vì' simplejson.dumps' trả về 'đối tượng không phải là JSON serializable' và' serializers.serialize' trả về 'đối tượng không có thuộc tính '_meta'' –

-1

Từ những gì tôi có thể hiểu được - và tôi mới đến python - với google app engine xung quanh là serialize đối tượng model cho một đối tượng python độc đoán và sau đó sử dụng json đơn giản để kết xuất nó như một chuỗi json - điều này không có ý nghĩa với tôi - có thể ai đó đã biết serialize cho một ditionary (pickel?) Bất kỳ trợ giúp nào về điều này sẽ là HELP! không gây ấn tượng rằng công cụ ứng dụng của google không có giải pháp sẵn có cho việc này.

+0

đã thử mã và nhận được lỗi này "return GqlEncoder(). Encode (input) RuntimeError: độ sâu đệ quy tối đa vượt quá" – jwesonga

14

Ok - python của tôi không lớn vì vậy bất kỳ trợ giúp sẽ được đánh giá cao - Bạn không cần phải viết một phân tích cú pháp - đây là giải pháp:

thêm này lớp utlity 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) 

tiết kiệm như json py

SỬ DỤNG

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() 

Đây là phản ứng của trình duyệt:

[{"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": "[email protected]", "email": "[email protected]", "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": "[email protected]", "email": "[email protected]", "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": "[email protected]", "email": "[email protected]", "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": "[email protected]", "email": "[email protected]", "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": "[email protected]", "email": "[email protected]", "auth_domain": "gmail.com"}}]

+0

Tôi đã thực hiện của riêng mình và nó rất gần với tệp bạn đã liên kết –

+0

Tuyệt vời, cảm ơn bạn. – Phil

+1

Không rõ ràng với tôi (người mới sử dụng python và GAE) nhưng bạn cần đưa mã mô-đun simplejson vào các tệp/gói GAE của bạn. – mataal

10

Ví dụ được cung cấp bởi Jader Dias hoạt động tốt cho mối quan tâm của tôi sau khi một số twaeking. Loại bỏ phương thức mã hóa vì nó chứa tham chiếu vòng tròn. Lớp điều chỉnh nên hình như:

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) 

Như tôi đã lưu lớp này trong một tập tin gọi là utils.py và khi thích hợp tôi import nó bằng lệnh

import utils 

Sau đó, tôi chỉ cần gọi utils.GqlEncoder () .encode (kết quả), ví dụ:

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)) 

kết quả sẽ giống như thế này (tôi đã thêm một số dòng nguồn cấp dữ liệu để làm cho nó một chút dễ dàng hơn để đọc):

[ 
{"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": "[email protected]", 
"full_name": "John Parnefjord" 
} 
] 
+0

Cảm ơn vì điều này! –

Các vấn đề liên quan