From 6c1a1271fb6cdee286713f7a1cfc512e6a7acee6 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Sun, 6 Mar 2022 15:25:53 -0800 Subject: [PATCH 1/7] Add an example for using a custom json encoder with media handlers. --- falcon/media/json.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/falcon/media/json.py b/falcon/media/json.py index e6cb0cf61..0c723732e 100644 --- a/falcon/media/json.py +++ b/falcon/media/json.py @@ -94,6 +94,37 @@ class JSONHandler(BaseHandler): ), ) + You can also override the JSONEncoder used by using a custom Encoder by + updating the media handlers for ``application/json`` type:: + + import json + from datetime import datetime + from functools import partial + + import falcon + from falcon import meda + + class DatetimeEncoder(json.JSONEncoder): + \"\"\"Json Encoder that supports datetime objects.\"\"\" + + def default(self, obj): + if isinstance(obj, datetime): + return obj.isoformat() + 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. From 874c540eedf57a52ff740e3868f3c8f85d143abe Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Mon, 7 Mar 2022 13:23:45 -0800 Subject: [PATCH 2/7] reword the doc to read better. --- falcon/media/json.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/falcon/media/json.py b/falcon/media/json.py index 0c723732e..93b90fd7d 100644 --- a/falcon/media/json.py +++ b/falcon/media/json.py @@ -94,8 +94,8 @@ class JSONHandler(BaseHandler): ), ) - You can also override the JSONEncoder used by using a custom Encoder by - updating the media handlers for ``application/json`` type:: + You can also override the default 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 c779b05f583bb17b232e12824aaf895657d28600 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Mon, 7 Mar 2022 13:34:38 -0800 Subject: [PATCH 3/7] Return the default. --- falcon/media/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/falcon/media/json.py b/falcon/media/json.py index 93b90fd7d..609b3eabd 100644 --- a/falcon/media/json.py +++ b/falcon/media/json.py @@ -110,7 +110,7 @@ class DatetimeEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.isoformat() - super().default(obj) + return super().default(obj) app = falcon.App() From 62c149db42226b222a523d03ffd534fb2b1a210d Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Mon, 7 Mar 2022 13:46:08 -0800 Subject: [PATCH 4/7] Cross-link from FAQ page for easier discovery. --- docs/user/faq.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/user/faq.rst b/docs/user/faq.rst index 9d3f09dd7..1c2d7c3f2 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 :class:`falcon.media.json.JSONHandler` for an exmaple 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 From eac7faafb72ddda8b095bf734195fe04cc76ffab Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Mon, 7 Mar 2022 13:49:48 -0800 Subject: [PATCH 5/7] Fix another typo. --- falcon/media/json.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/falcon/media/json.py b/falcon/media/json.py index 609b3eabd..f172753b8 100644 --- a/falcon/media/json.py +++ b/falcon/media/json.py @@ -102,7 +102,7 @@ class JSONHandler(BaseHandler): from functools import partial import falcon - from falcon import meda + from falcon import media class DatetimeEncoder(json.JSONEncoder): \"\"\"Json Encoder that supports datetime objects.\"\"\" From ef031414be46a12d5ff2bef783aed264de6547f3 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Mon, 7 Mar 2022 14:13:57 -0800 Subject: [PATCH 6/7] Fix a typo and use rubric for hyperlinks. --- docs/user/faq.rst | 2 +- falcon/media/json.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/user/faq.rst b/docs/user/faq.rst index 1c2d7c3f2..a55522a0c 100644 --- a/docs/user/faq.rst +++ b/docs/user/faq.rst @@ -915,7 +915,7 @@ 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 :class:`falcon.media.json.JSONHandler` for an exmaple on how to +.. seealso:: See :ref:`custom-media-json-encoder` for an example on how to use a custom json encoder. diff --git a/falcon/media/json.py b/falcon/media/json.py index f172753b8..f358fe9e6 100644 --- a/falcon/media/json.py +++ b/falcon/media/json.py @@ -94,6 +94,10 @@ class JSONHandler(BaseHandler): ), ) + .. _custom-media-json-encoder: + + .. rubric:: Custom Json Encoder + You can also override the default JSONEncoder by using a custom Encoder and updating the media handlers for ``application/json`` type to use that:: From f86435d0418d3559f1ffe8c6016466d913329105 Mon Sep 17 00:00:00 2001 From: Vytautas Liuolia Date: Tue, 8 Mar 2022 20:32:23 +0100 Subject: [PATCH 7/7] docs(media): tweak JSONHandler's rubrics --- docs/user/faq.rst | 2 +- falcon/media/json.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/user/faq.rst b/docs/user/faq.rst index a55522a0c..c16ed295e 100644 --- a/docs/user/faq.rst +++ b/docs/user/faq.rst @@ -916,7 +916,7 @@ 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. + use a custom json encoder. Does Falcon set Content-Length or do I need to do that explicitly? diff --git a/falcon/media/json.py b/falcon/media/json.py index f358fe9e6..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 @@ -96,10 +100,11 @@ class JSONHandler(BaseHandler): .. _custom-media-json-encoder: - .. rubric:: Custom Json Encoder + .. rubric:: Custom JSON encoder - You can also override the default JSONEncoder by using a custom Encoder and - updating the media handlers for ``application/json`` type to use that:: + 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