Repository: falconry/falcon

Issue:
Make JSONHandler customization docs clearer
As pointed out by @Stargateur in https://github.com/falconry/falcon/issues/1906#issuecomment-817374057, our [`JSONHandler`](https://falcon.readthedocs.io/en/stable/api/media.html#falcon.media.JSONHandler) customization docs could be made clearer by separately illustrating different (albeit closely related) concepts:
* Use a custom JSON library (such as the exemplified `rapidjson`). Customize parameters.
* Use the stdlib's `json` module, just provide custom serialization or deserialization parameters. Also link to the ["Prettifying JSON Responses" recipe](https://falcon.readthedocs.io/en/stable/user/recipes/pretty-json.html), which illustrates customization of `dumps` parameters.
* Add a sentence or two about replacing the default JSON handlers, not just toss in a code snippet as it is at the time of writing this. Also link to [Replacing the Default Handlers](https://falcon.readthedocs.io/en/stable/api/media.html#custom-media-handlers) from that explanation.


Discussion:
Hi, I can start working on this
Awesome, go ahead @dflss ! I'll remove the `needs contributor` label.

Resolving patch:
diff --git a/falcon/media/json.py b/falcon/media/json.py
--- a/falcon/media/json.py
+++ b/falcon/media/json.py
@@ -26,8 +26,10 @@ class JSONHandler(BaseHandler):
         library's JSON implementation, since it will be faster in most cases
         as compared to a third-party library.
 
-    Overriding the default JSON implementation is simply a matter of specifying
-    the desired ``dumps`` and ``loads`` functions::
+    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
+    ``loads`` functions::
 
         import falcon
         from falcon import media
@@ -46,13 +48,39 @@ class JSONHandler(BaseHandler):
         app.req_options.media_handlers.update(extra_handlers)
         app.resp_options.media_handlers.update(extra_handlers)
 
+    Even if you decide to stick with the stdlib's :any:`json.dump` and
+    :any:`json.loads`, you can wrap them using :any:`functools.partial` to
+    provide custom serialization or deserialization parameters supported by the
+    ``dumps`` and ``loads`` functions, respectively
+    (see also: :ref:`prettifying-json-responses`)::
+
+        import falcon
+        from falcon import media
+
+        from functools import partial
+
+        json_handler = media.JSONHandler(
+            dumps=partial(
+                json.dumps,
+                default=str,
+                sort_keys=True,
+            ),
+        )
+        extra_handlers = {
+            'application/json': json_handler,
+        }
+
+        app = falcon.App()
+        app.req_options.media_handlers.update(extra_handlers)
+        app.resp_options.media_handlers.update(extra_handlers)
+
     By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.
     If you override the ``dumps`` function, you will need to explicitly set
     ``ensure_ascii`` to ``False`` in order to enable the serialization of
     Unicode characters to UTF-8. This is easily done by using
-    :any:`functools.partial` to apply the desired keyword argument. In fact, you
-    can use this same technique to customize any option supported by the
-    ``dumps`` and ``loads`` functions::
+    :any:`functools.partial` to apply the desired keyword argument. As also
+    demonstrated in the previous paragraph, you can use this same technique to
+    customize any option supported by the ``dumps`` and ``loads`` functions::
 
         from functools import partial
 


Test patch: