Re: Configuring a specialized JSONEncoder for a renderer

72 views
Skip to first unread message

Chris McDonough

unread,
Jan 3, 2013, 11:43:41 AM1/3/13
to pylons-...@googlegroups.com
On Thu, 2013-01-03 at 06:16 -0800, Robert Smallshire wrote:
> I have access to a pre-existing json.JSONEncoder subclass called
> GpxJsonEncoder for serialising a specific type (called a GpxModel -
> although that's not important). I can use this specialised JSONEncoder
> with dumps() by specifying the 'cls' argument to json.dumps() and
> everything works as expected:
>
>
> import son
> json_data = json.dumps(gpx_model, cls=GpxJsonEncoder)
>
>
> I'd like to be able to use GpxJsonEncoder with Pyramid by configuring
> a gpx_json renderer for a view which could then just return a GpxModel
> instance. From reading the documentation I would expect to be able to
> do:
>
>
> config.add_renderer('json_gpx', JSON(cls=GpxJsonEncoder))
>
>
> since keyword arguments ('cls' in this case) are passed to the
> underlying serializer which is json.dumps().
>
>
> Unfortunately, this doesn't work as I would expect because Pyramid
> intervenes and passes a 'default' callback argument to the serializer
> which causes serialization to fail within the Pyramid defined default
> callback:
>
>
> File
> "/Users/rjs/dev/virtualenvs/sageroux/lib/python3.3/site-packages/pyramid/renderers.py", line 273, in default
> raise TypeError('%r is not JSON serializable' % (obj,))
> TypeError: <trailer.model.gpx_model.GpxModel object at
> 0x10a13c310> is not JSON serializable
>
>
> There doesn't seem to be any way to prevent Pyramid interjecting with
> this callback other than defining a customer serializer wrapping
> json.dumps() which accepts, but then ignores, the default argument,
> like this:
>
>
> def gpx_dumps(obj, default, **kwargs):
> # This function is just a wrapper for json.dumps() which
> ignores the
> # default parameter passed to the serializer by Pyramid, which
> would
> # otherwise cause the JSONEncoder subclass to fail.
> return json.dumps(obj, **kwargs)
>
>
> config.add_renderer('json_gpx', JSON(serializer=gpx_dumps,
> cls=GpxJsonEncoder))
>
>
> Is there are better solution for using off-the-shelf JSONEncoder
> subclasses? I think the API for JSON() needs to be slightly more
> flexible to avoid the need for the serializer wrapper. Should this be
> considered a bug or shortcoming in Pyramid?

I think it's just a mismatch between what you're calling an encoder and
what Pyramid expects of an encoder. Pyramid expects of an encoder what
json.encoder.JSONEncoder provides, including the fact that it accepts a
"default" argument with the same semantics as JSONEncoder. This is
actually spelled out in
http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/api/renderers.html?highlight=json#pyramid.renderers.JSON .

If your workaround works, though, I'd just use it.

- C

>
>
> Rob Smallshire
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "pylons-discuss" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/pylons-discuss/-/PDKRO6WCo2wJ.
> To post to this group, send email to pylons-...@googlegroups.com.
> To unsubscribe from this group, send email to pylons-discuss
> +unsub...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/pylons-discuss?hl=en.


Robert Smallshire

unread,
Jan 3, 2013, 1:05:03 PM1/3/13
to pylons-...@googlegroups.com
Well, my encoder, which is just the standard library json.dumps() method *does* accept a "default" argument along with the "cls" argument. The problem is that the implementation of "default" provided by Pyramid is incompatible with my (perhaps even any?) JSONEncoder subclass.  I know the specialized JSONEncoder works with json.dumps() in other contexts.  The problem is that there is no easy way to opt out of the Pyramid provided "default" implementation even though I know I don't want itor need it because there's an incompatibility between Pyramid's "default" and use of the the standard libary "cls" mechanism.

As you say, my workaround works, so I can just use it.


To unsubscribe from this group, send email to pylons-discus...@googlegroups.com.

Michael Merickel

unread,
Jan 3, 2013, 1:11:41 PM1/3/13
to Pylons

Pyramid's usage of default is the entire point of the hooks in the json renderer. It's where all types are adapted and __json__ methods are called. If you don't like that behavior then write your own renderer. It's not that hard.

I suspect that your JSONEncoder subclass just overrides default anyway. So why not just pull out that logic and pass it to the JSON renderer? Which is supported by python's dumps api as well. In fact I've seen very few good reasons to even make a JSONEncoder subclass at all.

Reply all
Reply to author
Forward
0 new messages