python - 使用装饰器对自定义对象进行编码 - Python

标签 python json dictionary decorator encoder

我正在寻找一种方法,使用类装饰器将自定义对象编码为 Python 中的字典,以提供应作为参数包含在生成的字典中的变量名称。有了字典,我就可以使用 json.dumps(custom_object_dict) 进行到 JSON 的转换。

换句话说,这个想法是有下面的@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")])

这个装饰器允许我做类似下面的事情:

选项 A:

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

选项 B:

json = json.dumps(course.dict_representation)

...或者类似的东西

所以问题是:如何编写这个编码器,唯一真正的要求是:

  1. 编码器应该只编码通过装饰器提供的变量
  2. 编码器应该能够编码其他对象(例如:类(class)中的教授,如果教授类也有装饰器@encoder
  3. 还应该能够编码其他对象的列表(例如:类(class)内的学生,算上学生也必须 @encoder 装饰器)

我研究了不同的方法(包括创建一个继承自 json.JSONEncoder 的类),但似乎没有一种方法完全符合我的想法。谁能帮帮我?

提前致谢!

最佳答案

也许是这样的(只是一个快速草图):

#! /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 或类似 if hasattr (v, __iter__) and not isinstance (v, str) 之外,您可能还想检查其他可迭代对象。

关于python - 使用装饰器对自定义对象进行编码 - Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14905985/

相关文章:

php - 以编程方式从 Google 获取关键字点击次数的最简单方法

python - 为什么 CPython Dicts 不受负一和负二哈希值的影响

python - 在 BeautifulSoup 中查找不同的字符串并返回包含标签

c# - 如何转换 Json key :value into value:value in C#?

python - 关于构建 selenium/python 框架的建议?

json - 有没有在不声明结构的情况下将编码结构作为 JSON 发送?

python - 如何有效地过滤具有任意长度元组作为键的字典?

Python - 比较两个列表以查找计数

python - 如何将 .whl 转换为 .egg?

python - 使用 Python Win32com 在 Outlook 中提取收件人电子邮件地址