Search code examples
pythonjsonpyramid

How to reuse a custom pyramid json renderer from inside a called __json__ or adapter?


Using pyramid, I have a hierarchy of objects I want to dump as json.

Some of these objects are not out of the box json serializable so I either implement json or have adapter's registered to a custom json_renderer that I have registered(so I don't need to monkey patch things like datetime).

Since they are nested(e.g there's a datetime further down that hierarchy) I can't just call up json.dumps within my classes json since it's not aware of the adapters.

I've tried to read through the source, and run this through the debugger and feel like I could go and pull the renderer from the registry and fiddle about with that? But I don't think that is the intended method. Surely there is something cleaner? Unfortunately all the examples in the docs are trivial.

How can I pass back serialization to the calling custom json renderer at json_dump_using_renderer()?

def custom_json_renderer():    
    def datetime_adapter(obj, request):
        return obj.isoformat()
    json_renderer = JSON()
    json_renderer.add_adapter(datetime.datetime, datetime_adapter)

class Whatever(object):
    def __init__(self, item):
        self.item = item

    def __json__(self):
        return "{ item: " + json_dump_using_renderer(obj.items) + "}"

Solution

  • So for starters your __json__ method should take (self, request) not just (self).. From there, you can use pyramid.renderers.render to perform a manual rendering if you want to embed a json-encoded string inside another data structure. Note that this will end up causing the item to be double-encoded but hopefully you're aware of that already.

    def __json__(self, request):
        return {'item': pyramid.renderers.render('json', obj.items, request=request)}
    

    Alternatively if you don't want the data to be double-encoded then you might just be asking why the adapters do not work on sub-items of an object returned from __json__ and the answer is that the adapters are implemented using the default argument of json.dumps and it just doesn't support what you want. You'd have to find a json serialization library that does... but I'm not aware of one.