Encoding custom objects using decorators - Python

I am looking for a way to encode custom objects for a dict in Python using a class decorator to provide the name of the variables that should be included in the resulting dict as arguments. With dict, I could use json.dumps(custom_object_dict) to convert JSON.

In other words, the idea is to have the following @encoder decorator:

 @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")]) 

This decorator will allow me to do something similar to the following:

Option A:

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

Option B:

 json = json.dumps(course.dict_representation) 

... Or something similar

So the question is: how to write this encoder, where the only real requirements are:

  • The encoder should only encode variables that are provided through the decorator.
  • The encoder should be able to encode other objects (for example, a professor inside the courses, if the professor's class also has the @encoder decorator
  • It should also be possible to encode a list of other objects (for example, students inside the course, assuming the class Students would also need @encoder decorator)

I explored various ways to do this (including creating a class that inherits from json.JSONEncoder), but no one seemed to do exactly what I had in mind. Can anyone help me?

Thanks in advance!

+4
source share
1 answer

Maybe something like this (just a quick sketch):

 #! /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) ) 

You might want to check other iterations besides list or something like if hasattr (v, __iter__) and not isinstance (v, str) .

+2
source

All Articles