Skip to content

Instantly share code, notes, and snippets.

@ojacobson
Created November 14, 2012 20:46
Show Gist options
  • Save ojacobson/4074689 to your computer and use it in GitHub Desktop.
Save ojacobson/4074689 to your computer and use it in GitHub Desktop.
def jsonizable(atoms=(), lists=(), objects=()):
"""Adds a `to_json` method to decorated classes:
>>> @jsonizable(atoms=['name', 'age'])
... class Example(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
...
>>> e = Example('bob', 37)
>>> e.to_json()
{'name': 'bob', 'age': 37}
JSON fields containing nested lists or collections must be handled specially:
>>> @jsonizable(atoms=['name'])
... class Person(object):
... def __init__(self, name):
... self.name = name
...
>>> @jsonizable(lists=['students'], objects=['teacher'])
... class Classroom(object):
... def __init__(self, students, teacher):
... self.students = students
... self.teacher = teacher
...
>>> students = [Person('bob'), Person('anne')]
>>> teacher = Person('clarice')
>>> classroom = Classroom(students, teacher)
>>> classroom.to_json()
{'students': [{'name': 'bob'}, {'name': 'anne'}], 'teacher': {'name': 'clarice'}}
The generated to_json method returns a `dict`, allowing callers to further
manipulate the JSON data before returning it.
The fields to include in the resulting `dict` are given by the optional
`atoms`, `lists`, and `objects` keyword arguments. Values from attributes
named in `atoms` will be included in the dict using the equivalent of
`getattr(self, atom_attr)`. Values of attributes named in `lists` will be
turned into lists using the equivalent of
`[v.to_json for v in getattr(self, list_attr)]`. Values of attributes named
in `objects` will be turned into nested JSON values using the equivalent
of `getattr(self, obj_attr).to_json() if getattr(self, obj_attr) else None`.
"""
def to_json(self):
json_data = dict()
for attribute in atoms:
json_data[attribute] = getattr(self, attribute)
for attribute in lists:
value = getattr(self, attribute)
if value is None:
json_data[attribute] = None
else:
json_data[attribute] = [element.to_json() for element in value]
for attribute in objects:
value = getattr(self, attribute)
if value is None:
json_data[attribute] = None
else:
json_data[attribute] = value.to_json()
return json_data
def decorator(cls):
cls.to_json = to_json
return cls
return decorator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment