2013-02-16 4 views
4

Я ищу способ кодирования пользовательских объектов для dict в Python с помощью декоратора класса, чтобы предоставить имя переменных, которые должны быть включены в результирующий dict в качестве аргументов. С помощью dict я смогу использовать json.dumps(custom_object_dict), чтобы преобразовать JSON.Кодирование пользовательских объектов с помощью декораторов - Python

Другими словами, идея состоит в том, чтобы иметь следующий @encoder класс декоратора:

@encoder(variables=['firstname', 'lastname'], objects=['professor'], lists=['students']) 
class Course(Object): 
    def __init__(self, firstname, lastname, professor, students): 
     self.firstname = firstname 
     self.lastname = lastname 
     self.professor = professor 
     self.students = students 

#instance of Course: 
course = Course("john", "smith", Professor(), [Student(1), Student(2, "john")]) 

Этот декоратор позволит мне сделать что-то похожее на следующее:

Вариант А:

json = json.dumps(course.to_dict()) 

Вариант B:

json = json.dumps(course.dict_representation) 

... Или что-то тому подобное

Таким образом, вопрос: Как написать этот кодер, где только реальные требования:

  1. кодировщик должен закодировать только переменные, которые предоставляются через декоратор
  2. кодировщик должен быть в состоянии кодировать другие объекты (например, профессор внутри курсов, если класс профессора также имеет декоратор @encoder
  3. следует также иметь возможность кодировать список других объектов (например: студенты в курсе, считая что студенты класса также должны @encoder декоратора)

Я исследовал различные способы сделать это (в том числе создание класса, который наследует от json.JSONEncoder), но никто не казалось, делать то, что я имел в виду. Кто-нибудь сможет мне помочь?

Заранее благодарен!

ответ

2

Может быть что-то вроде этого (просто быстрый эскиз):

#! /usr/bin/python3.2 

import json 

class Jsonable: 
    def __init__ (self, *args): 
     self.fields = args 

    def __call__ (self, cls): 
     cls._jsonFields = self.fields 
     def toDict (self): 
      d = {} 
      for f in self.__class__._jsonFields: 
       v = self.__getattribute__ (f) 
       if isinstance (v, list): 
        d [f] = [e.jsonDict if hasattr (e.__class__, '_jsonFields') else e for e in v] 
        continue 
       d [f] = v.jsonDict if hasattr (v.__class__, '_jsonFields') else v 
      return d 
     cls.toDict = toDict 

     oGetter = cls.__getattribute__ 
     def getter (self, key): 
      if key == 'jsonDict': return self.toDict() 
      return oGetter (self, key) 
     cls.__getattribute__ = getter 

     return cls 

@Jsonable ('professor', 'students', 'primitiveList') 
class Course: 
    def __init__ (self, professor, students): 
     self.professor = professor 
     self.students = students 
     self.toBeIgnored = 5 
     self.primitiveList = [0, 1, 1, 2, 3, 5] 

@Jsonable ('firstname', 'lastname') 
class Student: 
    def __init__ (self, firstname, lastname, score = 42): 
     self.firstname = firstname 
     self.lastname = lastname 
     self.score = score 

@Jsonable ('title', 'name') 
class Professor: 
    def __init__ (self, name, title): 
     self.title = title 
     self.name = name 

p = Professor ('Ordóñez', 'Dra') 
s1 = Student ('Juan', 'Pérez') 
s2 = Student ('Juana', 'López') 
s3 = Student ('Luis', 'Jerez') 
s4 = Student ('Luisa', 'Gómez') 
c = Course (p, [s1, s2, s3, s4]) 

print (json.dumps (c.jsonDict)) 

Вы можете проверить другие итерируемыми, кроме list или что-то вроде если hasattr (v, __iter__) and not isinstance (v, str).

+0

Это именно то, что я искал! Спасибо! –

+0

Добро пожаловать. – Hyperboreus

Смежные вопросы