Created
December 4, 2012 20:29
-
-
Save ojacobson/4208345 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
{'age': 37, 'name': 'bob'} | |
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()`. Both `lists` and | |
`objects` attributes are checked for `None`, and will be included in the | |
resulting dict with `None`. | |
You can, additionally, overlay values or computed values onto the JSON | |
representation by passing the optional `overlay` parameter as a dictionary | |
of callables: | |
>>> @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')] | |
>>> teacher = Person('clarice') | |
>>> classroom = Classroom(students, teacher) | |
>>> classroom.to_json(overlay=dict( | |
... address=lambda classroom: '1 Infinite Loop', | |
... students=dict( | |
... hat_size=lambda student: 'Large' | |
... ) | |
... )) | |
{'students': [{'name': 'bob', 'hat_size': 'Large'}], 'teacher': {'name': 'clarice'}, 'address': '1 Infinite Loop'} | |
""" | |
def to_json(self, overlay=None): | |
"""Returns a JSON representation of this object.""" | |
if overlay is None: | |
overlay = dict() | |
return _to_json(self, atoms, lists, objects, overlay) | |
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