Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check the __json__ magic method before serialising the object #116

Closed
wants to merge 2 commits into from
Closed

check the __json__ magic method before serialising the object #116

wants to merge 2 commits into from

Conversation

rach
Copy link

@rach rach commented Feb 21, 2013

To be more compliant with the current implementation of Pyramid:

http://docs.pylonsproject.org/projects/pyramid/en/master/narr/renderers.html#serializing-custom-objects

https://github.com/Pylons/pyramid/blob/master/pyramid/renderers.py#L263

It will be great if cornice could support the json method to makes life easier.

By the way, couldn't you reuse the Json Renderer from Pyramid and specify you own serializer

https://github.com/Pylons/pyramid/blob/master/pyramid/renderers.py#L263

 from pyramid.renderers impor JSON
 cornice_renderer = JSON(serializer=simplejson.dumps)

@almet
Copy link
Contributor

almet commented Feb 20, 2013

Hi @rach,

I'm not sure to completely get what your proposition is. You already can put the renderer you want with cornice.
Do you have a use case in mind, something where cornice is preventing you to acomplish JSON serialisation the way you want?

@rach
Copy link
Author

rach commented Feb 20, 2013

It's more about coherency with the default json renderer from pyramid.
I was already using json to serialize some object, when I started to use cornice. I got surprise that it didn't work and checked the doc and src.

json_renderer = JSON()
def datetime_adapter(obj, request):
    return obj.isoformat()
json_renderer.add_adapter(datetime.datetime, datetime_adapter)
config.add_renderer('json',json_renderer)

I found a bit weird that the same behaviour is not respected.
But like you say it can be changed and work wells, but it guess make the move from the default json renderer to cornice one more smooth.

Now because I didn't wanted to change the renderer on all my Service so I'm having:

json_renderer = JSON(serialiser=simplejson.dumps)
def datetime_adapter(obj, request):
    return obj.isoformat()
json_renderer.add_adapter(datetime.datetime, datetime_adapter)
config.add_renderer('simplejson',json_renderer)

I guess that I'm missing the point why Cornice is creating its own renderer and is not reusing the one of pyramid.

@rach
Copy link
Author

rach commented Feb 20, 2013

Hi @ametaireau

Just to resume, it's suggestion for an improvement and not a bug at all.

Feel free to close this issue, if it's out the scope .

@almet
Copy link
Contributor

almet commented Feb 20, 2013

I thnk we should use the default JSON serializer, you're right, if it handles datetime serialisation.

@rach
Copy link
Author

rach commented Feb 20, 2013

The default serializer is very nice and have a method add_adapter to extend it ...
See my example above to support datetime easily and it can be applied to much more complex object.

I have some code already done at home, I can add a pull request later on.

I realize that I wasn't very clear at the start.

Pyramid has a json renderer which allow to precis the serializer.
This allow to use renderer adapter to add behavior when some types
are detected plus the check of the __json__ method on returned object.
See #116
@tdavis
Copy link

tdavis commented Feb 21, 2013

@rach Looks like you need to update the tests to check for application/json content-type, not text/json.

@rach
Copy link
Author

rach commented Feb 21, 2013

The test was already broken.
I thought about fixing it, I was not sure about the expected result and if
it's the test that need to be fixed or the source
Check the travis-ci history.
On Feb 21, 2013 2:20 PM, "Tom Davis" [email protected] wrote:

@rach https://github.com/rach Looks like you need to update the tests
to check for application/json content-type, not text/json.


Reply to this email directly or view it on GitHubhttps://github.com//pull/116#issuecomment-13890642.

@almet
Copy link
Contributor

almet commented Feb 21, 2013

yeah that's unrelated to this patch.



__all__ = ['json_renderer', 'to_list', 'json_error', 'match_accept_header',
__all__ = ['json_datetime_adapter', 'json_decimal_adapter', 'json_renderer', 'to_list', 'json_error', 'match_accept_header',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really want to expose these?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you want, happy to remove it.

It's reusable but maybe not useful to expose it.
I had initially exposed it because I was building the renderer in the
init

On Thu, Feb 21, 2013 at 2:46 PM, Alexis Metaireau
[email protected]:

In cornice/util.py:

-all = ['json_renderer', 'to_list', 'json_error', 'match_accept_header',
+all = ['json_datetime_adapter', 'json_decimal_adapter', 'json_renderer', 'to_list', 'json_error', 'match_accept_header',

do we really want to expose these?


Reply to this email directly or view it on GitHubhttps://github.com//pull/116/files#r3099381.

Rach Belaid
Director at Iron Braces Ltd
Flat 9 240B Amhurst Road, London N16 7UL
Phone : +44 75 008 660 84
VAT : 114 2764 36

@rach
Copy link
Author

rach commented Feb 22, 2013

I removed the exposed adapter in the case that it's not use anywhere else

@rach
Copy link
Author

rach commented Feb 22, 2013

Maybe worth adding few words in the doc about the json method that can be implemented on object returned for helping the serialization
http://docs.pylonsproject.org/projects/pyramid/en/master/narr/renderers.html#serializing-custom-objects

@almet
Copy link
Contributor

almet commented Feb 22, 2013

Yep that would be useful to point this out, agreed.

@almet
Copy link
Contributor

almet commented Mar 3, 2013

Actually, we in the mean time introduced some behaviour which depends on having a custom JSON Serializer (which returns the good Content-Type, using the request "accept" headers).

So in its current state, it's not possible for me to merge this, because of this particular behaviour.
However, I like the idea of using the default serializer of pyramid, and would love to do so. What we're missing is a way to make it change the content-type of its response on the fly.

Do you think this could be possible?

@rach
Copy link
Author

rach commented Mar 3, 2013

Hi,

I can imagine that can be very useful for building services.

I guess that you refer to this line?

https://github.com/mozilla-services/cornice/blob/master/cornice/util.py#L21
You could maybe use the event 'NewResponse' or 'NewRequest'

And then change the conten-type via the request.response but I'm not a
fan of this solution.

I'm not familiar with all the cornice codebase but I noticed that you are
already using some even/hooks and other predicate in the pyramidhook.py .

Now I don't know what happen when you change the response.content-type
before going through the renderer if it's ignored or kept.

Need to be tested.

On Sun, Mar 3, 2013 at 9:29 PM, Alexis Metaireau
[email protected]:

Actually, we in the mean time introduced some behaviour which depends on
having a custom JSON Serializer (which returns the good Content-Type, using
the request "accept" headers).

So in its current state, it's not possible for me to merge this, because
of this particular behaviour.
However, I like the idea of using the default serializer of pyramid, and
would love to do so. What we're missing is a way to make it change the
content-type of its response on the fly.

Do you think this could be possible?


Reply to this email directly or view it on GitHubhttps://github.com//pull/116#issuecomment-14355865
.

Rach Belaid
Director at Iron Braces Ltd
Flat 9 240B Amhurst Road, London N16 7UL
Phone : +44 75 008 660 84
VAT : 114 2764 36

@leplatrem
Copy link
Contributor

Sorry to come on top of your contribution, but it seems appropriate (and related) to discuss date/datetime JSON serialization here :)

Is there any working solution ?

Stacktrace is here : https://travis-ci.org/spiral-project/daybed/jobs/9473751#L420

I tried this, without success :

from .renderers import JSONP

config.add_renderer('jsonp', JSONP(param_name='callback'))
+# renderers.py
+import json
+from datetime import date, datetime
+from decimal import Decimal
+
+from pyramid.renderers import JSONP as PyramidJSONP
+
+
+def json_datetime_adapter(obj, request):
+    return obj.isoformat()
+
+
+def json_decimal_adapter(obj, request):
+    return json.dumps(obj, use_decimal=True)
+
+
+class JSONP(PyramidJSONP):
+    def __init__(self, *args, **kwargs):
+        super(JSONP, self).__init__(*args, **kwargs)
+        self.add_adapter(date, json_datetime_adapter)
+        self.add_adapter(datetime, json_datetime_adapter)
+        self.add_adapter(Decimal, json_decimal_adapter)

Thanks !

@matleh
Copy link

matleh commented Jul 25, 2013

@leplatrem: the error_handler, that is called when a validation added a error to request.errors does not use the registered JSON renderer, but simply does json.dumps(..).

I was suprised by this, too. But this is probably an issue for itself.

@leplatrem
Copy link
Contributor

Thanks for your reply !
Looks indeed like an issue, but having complex data structure in errors messages should be avoided IHMO

My issue was precisely due to a couchdb storage somewhere else in the code :) But your message helped me to understand some cornice mechanics, since I was first focused on error handling :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants