From 89a615a4d7f6bb9ca6ae48dcccb53b172fd90ed2 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Tue, 8 Mar 2022 13:34:31 -0800 Subject: [PATCH] docs(media): add an example for using a custom JSON encoder (#2035) * Add an example for using a custom json encoder with media handlers. * reword the doc to read better. * Return the default. * Cross-link from FAQ page for easier discovery. * Fix another typo. * Fix a typo and use rubric for hyperlinks. * docs(media): tweak JSONHandler's rubrics Co-authored-by: Vytautas Liuolia --- docs/user/faq.rst | 4 ++++ falcon/media/json.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/docs/user/faq.rst b/docs/user/faq.rst index 9d3f09dd7..c16ed295e 100644 --- a/docs/user/faq.rst +++ b/docs/user/faq.rst @@ -915,6 +915,10 @@ Furthermore, different Internet media types such as YAML, types than JSON, either as part of the respective (de)serialization format, or via custom type extensions. +.. seealso:: See :ref:`custom-media-json-encoder` for an example on how to + use a custom json encoder. + + Does Falcon set Content-Length or do I need to do that explicitly? ------------------------------------------------------------------ Falcon will try to do this for you, based on the value of diff --git a/falcon/media/json.py b/falcon/media/json.py index e6cb0cf61..47b91a516 100644 --- a/falcon/media/json.py +++ b/falcon/media/json.py @@ -26,6 +26,8 @@ class JSONHandler(BaseHandler): library's JSON implementation, since it will be faster in most cases as compared to a third-party library. + .. rubric:: Custom JSON library + You can replace the default JSON handler by using a custom JSON library (see also: :ref:`custom_media_handlers`). Overriding the default JSON implementation is simply a matter of specifying the desired ``dumps`` and @@ -48,6 +50,8 @@ class JSONHandler(BaseHandler): app.req_options.media_handlers.update(extra_handlers) app.resp_options.media_handlers.update(extra_handlers) + .. rubric:: Custom serialization parameters + Even if you decide to stick with the stdlib's :any:`json.dumps` and :any:`json.loads`, you can wrap them using :any:`functools.partial` to provide custom serialization or deserialization parameters supported by the @@ -94,6 +98,42 @@ class JSONHandler(BaseHandler): ), ) + .. _custom-media-json-encoder: + + .. rubric:: Custom JSON encoder + + You can also override the default :class:`~json.JSONEncoder` by using a + custom Encoder and updating the media handlers for ``application/json`` + type to use that:: + + import json + from datetime import datetime + from functools import partial + + import falcon + from falcon import media + + class DatetimeEncoder(json.JSONEncoder): + \"\"\"Json Encoder that supports datetime objects.\"\"\" + + def default(self, obj): + if isinstance(obj, datetime): + return obj.isoformat() + return super().default(obj) + + app = falcon.App() + + json_handler = media.JSONHandler( + dumps=partial(json.dumps, cls=DatetimeEncoder), + ) + extra_handlers = { + 'application/json': json_handler, + } + + app.req_options.media_handlers.update(extra_handlers) + app.resp_options.media_handlers.update(extra_handlers) + + Keyword Arguments: dumps (func): Function to use when serializing JSON responses. loads (func): Function to use when deserializing JSON requests.