We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `falcon/media/json.py`
Content:
```
1 from functools import partial
2 import json
3 
4 from falcon import errors
5 from falcon import http_error
6 from falcon.media.base import BaseHandler
7 from falcon.media.base import TextBaseHandlerWS
8 
9 
10 class JSONHandler(BaseHandler):
11     """JSON media handler.
12 
13     This handler uses Python's standard :py:mod:`json` library by default, but
14     can be easily configured to use any of a number of third-party JSON
15     libraries, depending on your needs. For example, you can often
16     realize a significant performance boost under CPython by using an
17     alternative library. Good options in this respect include `orjson`,
18     `python-rapidjson`, and `mujson`.
19 
20     This handler will raise a :class:`falcon.MediaNotFoundError` when attempting
21     to parse an empty body, or a :class:`falcon.MediaMalformedError`
22     if an error happens while parsing the body.
23 
24     Note:
25         If you are deploying to PyPy, we recommend sticking with the standard
26         library's JSON implementation, since it will be faster in most cases
27         as compared to a third-party library.
28 
29     Overriding the default JSON implementation is simply a matter of specifying
30     the desired ``dumps`` and ``loads`` functions::
31 
32         import falcon
33         from falcon import media
34 
35         import rapidjson
36 
37         json_handler = media.JSONHandler(
38             dumps=rapidjson.dumps,
39             loads=rapidjson.loads,
40         )
41         extra_handlers = {
42             'application/json': json_handler,
43         }
44 
45         app = falcon.App()
46         app.req_options.media_handlers.update(extra_handlers)
47         app.resp_options.media_handlers.update(extra_handlers)
48 
49     By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.
50     If you override the ``dumps`` function, you will need to explicitly set
51     ``ensure_ascii`` to ``False`` in order to enable the serialization of
52     Unicode characters to UTF-8. This is easily done by using
53     :any:`functools.partial` to apply the desired keyword argument. In fact, you
54     can use this same technique to customize any option supported by the
55     ``dumps`` and ``loads`` functions::
56 
57         from functools import partial
58 
59         from falcon import media
60         import rapidjson
61 
62         json_handler = media.JSONHandler(
63             dumps=partial(
64                 rapidjson.dumps,
65                 ensure_ascii=False, sort_keys=True
66             ),
67         )
68 
69     Keyword Arguments:
70         dumps (func): Function to use when serializing JSON responses.
71         loads (func): Function to use when deserializing JSON requests.
72     """
73 
74     def __init__(self, dumps=None, loads=None):
75         self._dumps = dumps or partial(json.dumps, ensure_ascii=False)
76         self._loads = loads or json.loads
77 
78         # PERF(kgriffs): Test dumps once up front so we can set the
79         #     proper serialize implementation.
80         result = self._dumps({'message': 'Hello World'})
81         if isinstance(result, str):
82             self.serialize = self._serialize_s
83             self.serialize_async = self._serialize_async_s
84         else:
85             self.serialize = self._serialize_b
86             self.serialize_async = self._serialize_async_b
87 
88         # NOTE(kgriffs): To be safe, only enable the optimized protocol when
89         #   not subclassed.
90         if type(self) is JSONHandler:
91             self._serialize_sync = self.serialize
92             self._deserialize_sync = self._deserialize
93 
94     def _deserialize(self, data):
95         if not data:
96             raise errors.MediaNotFoundError('JSON')
97         try:
98             return self._loads(data.decode())
99         except ValueError as err:
100             raise errors.MediaMalformedError('JSON') from err
101 
102     def deserialize(self, stream, content_type, content_length):
103         return self._deserialize(stream.read())
104 
105     async def deserialize_async(self, stream, content_type, content_length):
106         return self._deserialize(await stream.read())
107 
108     # NOTE(kgriffs): Make content_type a kwarg to support the
109     #   Request.render_body() shortcut optimization.
110     def _serialize_s(self, media, content_type=None) -> bytes:
111         return self._dumps(media).encode()
112 
113     async def _serialize_async_s(self, media, content_type) -> bytes:
114         return self._dumps(media).encode()
115 
116     def _serialize_b(self, media, content_type) -> bytes:
117         return self._dumps(media)
118 
119     async def _serialize_async_b(self, media, content_type) -> bytes:
120         return self._dumps(media)
121 
122 
123 class JSONHandlerWS(TextBaseHandlerWS):
124     """WebSocket media handler for de(serializing) JSON to/from TEXT payloads.
125 
126     This handler uses Python's standard :py:mod:`json` library by default, but
127     can be easily configured to use any of a number of third-party JSON
128     libraries, depending on your needs. For example, you can often
129     realize a significant performance boost under CPython by using an
130     alternative library. Good options in this respect include `orjson`,
131     `python-rapidjson`, and `mujson`.
132 
133     Note:
134         If you are deploying to PyPy, we recommend sticking with the standard
135         library's JSON implementation, since it will be faster in most cases
136         as compared to a third-party library.
137 
138     Overriding the default JSON implementation is simply a matter of specifying
139     the desired ``dumps`` and ``loads`` functions::
140 
141         import falcon
142         from falcon import media
143 
144         import rapidjson
145 
146         json_handler = media.JSONHandlerWS(
147             dumps=rapidjson.dumps,
148             loads=rapidjson.loads,
149         )
150 
151         app = falcon.asgi.App()
152         app.ws_options.media_handlers[falcon.WebSocketPayloadType.TEXT] = json_handler
153 
154     By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.
155     If you override the ``dumps`` function, you will need to explicitly set
156     ``ensure_ascii`` to ``False`` in order to enable the serialization of
157     Unicode characters to UTF-8. This is easily done by using
158     :any:`functools.partial` to apply the desired keyword argument. In fact, you
159     can use this same technique to customize any option supported by the
160     ``dumps`` and ``loads`` functions::
161 
162         from functools import partial
163 
164         from falcon import media
165         import rapidjson
166 
167         json_handler = media.JSONHandlerWS(
168             dumps=partial(
169                 rapidjson.dumps,
170                 ensure_ascii=False, sort_keys=True
171             ),
172         )
173 
174     Keyword Arguments:
175         dumps (func): Function to use when serializing JSON.
176         loads (func): Function to use when deserializing JSON.
177     """
178 
179     __slots__ = ['dumps', 'loads']
180 
181     def __init__(self, dumps=None, loads=None):
182         self._dumps = dumps or partial(json.dumps, ensure_ascii=False)
183         self._loads = loads or json.loads
184 
185     def serialize(self, media: object) -> str:
186         return self._dumps(media)
187 
188     def deserialize(self, payload: str) -> object:
189         return self._loads(payload)
190 
191 
192 http_error._DEFAULT_JSON_HANDLER = _DEFAULT_JSON_HANDLER = JSONHandler()  # type: ignore
193
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 @@
         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 @@
         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

{"golden_diff": "diff --git a/falcon/media/json.py b/falcon/media/json.py\n--- a/falcon/media/json.py\n+++ b/falcon/media/json.py\n@@ -26,8 +26,10 @@\n         library's JSON implementation, since it will be faster in most cases\n         as compared to a third-party library.\n \n-    Overriding the default JSON implementation is simply a matter of specifying\n-    the desired ``dumps`` and ``loads`` functions::\n+    You can replace the default JSON handler by using a custom JSON library\n+    (see also: :ref:`custom_media_handlers`). Overriding the default JSON\n+    implementation is simply a matter of specifying the desired ``dumps`` and\n+    ``loads`` functions::\n \n         import falcon\n         from falcon import media\n@@ -46,13 +48,39 @@\n         app.req_options.media_handlers.update(extra_handlers)\n         app.resp_options.media_handlers.update(extra_handlers)\n \n+    Even if you decide to stick with the stdlib's :any:`json.dump` and\n+    :any:`json.loads`, you can wrap them using :any:`functools.partial` to\n+    provide custom serialization or deserialization parameters supported by the\n+    ``dumps`` and ``loads`` functions, respectively\n+    (see also: :ref:`prettifying-json-responses`)::\n+\n+        import falcon\n+        from falcon import media\n+\n+        from functools import partial\n+\n+        json_handler = media.JSONHandler(\n+            dumps=partial(\n+                json.dumps,\n+                default=str,\n+                sort_keys=True,\n+            ),\n+        )\n+        extra_handlers = {\n+            'application/json': json_handler,\n+        }\n+\n+        app = falcon.App()\n+        app.req_options.media_handlers.update(extra_handlers)\n+        app.resp_options.media_handlers.update(extra_handlers)\n+\n     By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.\n     If you override the ``dumps`` function, you will need to explicitly set\n     ``ensure_ascii`` to ``False`` in order to enable the serialization of\n     Unicode characters to UTF-8. This is easily done by using\n-    :any:`functools.partial` to apply the desired keyword argument. In fact, you\n-    can use this same technique to customize any option supported by the\n-    ``dumps`` and ``loads`` functions::\n+    :any:`functools.partial` to apply the desired keyword argument. As also\n+    demonstrated in the previous paragraph, you can use this same technique to\n+    customize any option supported by the ``dumps`` and ``loads`` functions::\n \n         from functools import partial\n", "issue": "Make JSONHandler customization docs clearer\nAs 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:\r\n* Use a custom JSON library (such as the exemplified `rapidjson`). Customize parameters.\r\n* 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.\r\n* 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.\n", "before_files": [{"content": "from functools import partial\nimport json\n\nfrom falcon import errors\nfrom falcon import http_error\nfrom falcon.media.base import BaseHandler\nfrom falcon.media.base import TextBaseHandlerWS\n\n\nclass JSONHandler(BaseHandler):\n    \"\"\"JSON media handler.\n\n    This handler uses Python's standard :py:mod:`json` library by default, but\n    can be easily configured to use any of a number of third-party JSON\n    libraries, depending on your needs. For example, you can often\n    realize a significant performance boost under CPython by using an\n    alternative library. Good options in this respect include `orjson`,\n    `python-rapidjson`, and `mujson`.\n\n    This handler will raise a :class:`falcon.MediaNotFoundError` when attempting\n    to parse an empty body, or a :class:`falcon.MediaMalformedError`\n    if an error happens while parsing the body.\n\n    Note:\n        If you are deploying to PyPy, we recommend sticking with the standard\n        library's JSON implementation, since it will be faster in most cases\n        as compared to a third-party library.\n\n    Overriding the default JSON implementation is simply a matter of specifying\n    the desired ``dumps`` and ``loads`` functions::\n\n        import falcon\n        from falcon import media\n\n        import rapidjson\n\n        json_handler = media.JSONHandler(\n            dumps=rapidjson.dumps,\n            loads=rapidjson.loads,\n        )\n        extra_handlers = {\n            'application/json': json_handler,\n        }\n\n        app = falcon.App()\n        app.req_options.media_handlers.update(extra_handlers)\n        app.resp_options.media_handlers.update(extra_handlers)\n\n    By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.\n    If you override the ``dumps`` function, you will need to explicitly set\n    ``ensure_ascii`` to ``False`` in order to enable the serialization of\n    Unicode characters to UTF-8. This is easily done by using\n    :any:`functools.partial` to apply the desired keyword argument. In fact, you\n    can use this same technique to customize any option supported by the\n    ``dumps`` and ``loads`` functions::\n\n        from functools import partial\n\n        from falcon import media\n        import rapidjson\n\n        json_handler = media.JSONHandler(\n            dumps=partial(\n                rapidjson.dumps,\n                ensure_ascii=False, sort_keys=True\n            ),\n        )\n\n    Keyword Arguments:\n        dumps (func): Function to use when serializing JSON responses.\n        loads (func): Function to use when deserializing JSON requests.\n    \"\"\"\n\n    def __init__(self, dumps=None, loads=None):\n        self._dumps = dumps or partial(json.dumps, ensure_ascii=False)\n        self._loads = loads or json.loads\n\n        # PERF(kgriffs): Test dumps once up front so we can set the\n        #     proper serialize implementation.\n        result = self._dumps({'message': 'Hello World'})\n        if isinstance(result, str):\n            self.serialize = self._serialize_s\n            self.serialize_async = self._serialize_async_s\n        else:\n            self.serialize = self._serialize_b\n            self.serialize_async = self._serialize_async_b\n\n        # NOTE(kgriffs): To be safe, only enable the optimized protocol when\n        #   not subclassed.\n        if type(self) is JSONHandler:\n            self._serialize_sync = self.serialize\n            self._deserialize_sync = self._deserialize\n\n    def _deserialize(self, data):\n        if not data:\n            raise errors.MediaNotFoundError('JSON')\n        try:\n            return self._loads(data.decode())\n        except ValueError as err:\n            raise errors.MediaMalformedError('JSON') from err\n\n    def deserialize(self, stream, content_type, content_length):\n        return self._deserialize(stream.read())\n\n    async def deserialize_async(self, stream, content_type, content_length):\n        return self._deserialize(await stream.read())\n\n    # NOTE(kgriffs): Make content_type a kwarg to support the\n    #   Request.render_body() shortcut optimization.\n    def _serialize_s(self, media, content_type=None) -> bytes:\n        return self._dumps(media).encode()\n\n    async def _serialize_async_s(self, media, content_type) -> bytes:\n        return self._dumps(media).encode()\n\n    def _serialize_b(self, media, content_type) -> bytes:\n        return self._dumps(media)\n\n    async def _serialize_async_b(self, media, content_type) -> bytes:\n        return self._dumps(media)\n\n\nclass JSONHandlerWS(TextBaseHandlerWS):\n    \"\"\"WebSocket media handler for de(serializing) JSON to/from TEXT payloads.\n\n    This handler uses Python's standard :py:mod:`json` library by default, but\n    can be easily configured to use any of a number of third-party JSON\n    libraries, depending on your needs. For example, you can often\n    realize a significant performance boost under CPython by using an\n    alternative library. Good options in this respect include `orjson`,\n    `python-rapidjson`, and `mujson`.\n\n    Note:\n        If you are deploying to PyPy, we recommend sticking with the standard\n        library's JSON implementation, since it will be faster in most cases\n        as compared to a third-party library.\n\n    Overriding the default JSON implementation is simply a matter of specifying\n    the desired ``dumps`` and ``loads`` functions::\n\n        import falcon\n        from falcon import media\n\n        import rapidjson\n\n        json_handler = media.JSONHandlerWS(\n            dumps=rapidjson.dumps,\n            loads=rapidjson.loads,\n        )\n\n        app = falcon.asgi.App()\n        app.ws_options.media_handlers[falcon.WebSocketPayloadType.TEXT] = json_handler\n\n    By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.\n    If you override the ``dumps`` function, you will need to explicitly set\n    ``ensure_ascii`` to ``False`` in order to enable the serialization of\n    Unicode characters to UTF-8. This is easily done by using\n    :any:`functools.partial` to apply the desired keyword argument. In fact, you\n    can use this same technique to customize any option supported by the\n    ``dumps`` and ``loads`` functions::\n\n        from functools import partial\n\n        from falcon import media\n        import rapidjson\n\n        json_handler = media.JSONHandlerWS(\n            dumps=partial(\n                rapidjson.dumps,\n                ensure_ascii=False, sort_keys=True\n            ),\n        )\n\n    Keyword Arguments:\n        dumps (func): Function to use when serializing JSON.\n        loads (func): Function to use when deserializing JSON.\n    \"\"\"\n\n    __slots__ = ['dumps', 'loads']\n\n    def __init__(self, dumps=None, loads=None):\n        self._dumps = dumps or partial(json.dumps, ensure_ascii=False)\n        self._loads = loads or json.loads\n\n    def serialize(self, media: object) -> str:\n        return self._dumps(media)\n\n    def deserialize(self, payload: str) -> object:\n        return self._loads(payload)\n\n\nhttp_error._DEFAULT_JSON_HANDLER = _DEFAULT_JSON_HANDLER = JSONHandler()  # type: ignore\n", "path": "falcon/media/json.py"}], "after_files": [{"content": "from functools import partial\nimport json\n\nfrom falcon import errors\nfrom falcon import http_error\nfrom falcon.media.base import BaseHandler\nfrom falcon.media.base import TextBaseHandlerWS\n\n\nclass JSONHandler(BaseHandler):\n    \"\"\"JSON media handler.\n\n    This handler uses Python's standard :py:mod:`json` library by default, but\n    can be easily configured to use any of a number of third-party JSON\n    libraries, depending on your needs. For example, you can often\n    realize a significant performance boost under CPython by using an\n    alternative library. Good options in this respect include `orjson`,\n    `python-rapidjson`, and `mujson`.\n\n    This handler will raise a :class:`falcon.MediaNotFoundError` when attempting\n    to parse an empty body, or a :class:`falcon.MediaMalformedError`\n    if an error happens while parsing the body.\n\n    Note:\n        If you are deploying to PyPy, we recommend sticking with the standard\n        library's JSON implementation, since it will be faster in most cases\n        as compared to a third-party library.\n\n    You can replace the default JSON handler by using a custom JSON library\n    (see also: :ref:`custom_media_handlers`). Overriding the default JSON\n    implementation is simply a matter of specifying the desired ``dumps`` and\n    ``loads`` functions::\n\n        import falcon\n        from falcon import media\n\n        import rapidjson\n\n        json_handler = media.JSONHandler(\n            dumps=rapidjson.dumps,\n            loads=rapidjson.loads,\n        )\n        extra_handlers = {\n            'application/json': json_handler,\n        }\n\n        app = falcon.App()\n        app.req_options.media_handlers.update(extra_handlers)\n        app.resp_options.media_handlers.update(extra_handlers)\n\n    Even if you decide to stick with the stdlib's :any:`json.dump` and\n    :any:`json.loads`, you can wrap them using :any:`functools.partial` to\n    provide custom serialization or deserialization parameters supported by the\n    ``dumps`` and ``loads`` functions, respectively\n    (see also: :ref:`prettifying-json-responses`)::\n\n        import falcon\n        from falcon import media\n\n        from functools import partial\n\n        json_handler = media.JSONHandler(\n            dumps=partial(\n                json.dumps,\n                default=str,\n                sort_keys=True,\n            ),\n        )\n        extra_handlers = {\n            'application/json': json_handler,\n        }\n\n        app = falcon.App()\n        app.req_options.media_handlers.update(extra_handlers)\n        app.resp_options.media_handlers.update(extra_handlers)\n\n    By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.\n    If you override the ``dumps`` function, you will need to explicitly set\n    ``ensure_ascii`` to ``False`` in order to enable the serialization of\n    Unicode characters to UTF-8. This is easily done by using\n    :any:`functools.partial` to apply the desired keyword argument. As also\n    demonstrated in the previous paragraph, you can use this same technique to\n    customize any option supported by the ``dumps`` and ``loads`` functions::\n\n        from functools import partial\n\n        from falcon import media\n        import rapidjson\n\n        json_handler = media.JSONHandler(\n            dumps=partial(\n                rapidjson.dumps,\n                ensure_ascii=False, sort_keys=True\n            ),\n        )\n\n    Keyword Arguments:\n        dumps (func): Function to use when serializing JSON responses.\n        loads (func): Function to use when deserializing JSON requests.\n    \"\"\"\n\n    def __init__(self, dumps=None, loads=None):\n        self._dumps = dumps or partial(json.dumps, ensure_ascii=False)\n        self._loads = loads or json.loads\n\n        # PERF(kgriffs): Test dumps once up front so we can set the\n        #     proper serialize implementation.\n        result = self._dumps({'message': 'Hello World'})\n        if isinstance(result, str):\n            self.serialize = self._serialize_s\n            self.serialize_async = self._serialize_async_s\n        else:\n            self.serialize = self._serialize_b\n            self.serialize_async = self._serialize_async_b\n\n        # NOTE(kgriffs): To be safe, only enable the optimized protocol when\n        #   not subclassed.\n        if type(self) is JSONHandler:\n            self._serialize_sync = self.serialize\n            self._deserialize_sync = self._deserialize\n\n    def _deserialize(self, data):\n        if not data:\n            raise errors.MediaNotFoundError('JSON')\n        try:\n            return self._loads(data.decode())\n        except ValueError as err:\n            raise errors.MediaMalformedError('JSON') from err\n\n    def deserialize(self, stream, content_type, content_length):\n        return self._deserialize(stream.read())\n\n    async def deserialize_async(self, stream, content_type, content_length):\n        return self._deserialize(await stream.read())\n\n    # NOTE(kgriffs): Make content_type a kwarg to support the\n    #   Request.render_body() shortcut optimization.\n    def _serialize_s(self, media, content_type=None) -> bytes:\n        return self._dumps(media).encode()\n\n    async def _serialize_async_s(self, media, content_type) -> bytes:\n        return self._dumps(media).encode()\n\n    def _serialize_b(self, media, content_type) -> bytes:\n        return self._dumps(media)\n\n    async def _serialize_async_b(self, media, content_type) -> bytes:\n        return self._dumps(media)\n\n\nclass JSONHandlerWS(TextBaseHandlerWS):\n    \"\"\"WebSocket media handler for de(serializing) JSON to/from TEXT payloads.\n\n    This handler uses Python's standard :py:mod:`json` library by default, but\n    can be easily configured to use any of a number of third-party JSON\n    libraries, depending on your needs. For example, you can often\n    realize a significant performance boost under CPython by using an\n    alternative library. Good options in this respect include `orjson`,\n    `python-rapidjson`, and `mujson`.\n\n    Note:\n        If you are deploying to PyPy, we recommend sticking with the standard\n        library's JSON implementation, since it will be faster in most cases\n        as compared to a third-party library.\n\n    Overriding the default JSON implementation is simply a matter of specifying\n    the desired ``dumps`` and ``loads`` functions::\n\n        import falcon\n        from falcon import media\n\n        import rapidjson\n\n        json_handler = media.JSONHandlerWS(\n            dumps=rapidjson.dumps,\n            loads=rapidjson.loads,\n        )\n\n        app = falcon.asgi.App()\n        app.ws_options.media_handlers[falcon.WebSocketPayloadType.TEXT] = json_handler\n\n    By default, ``ensure_ascii`` is passed to the ``json.dumps`` function.\n    If you override the ``dumps`` function, you will need to explicitly set\n    ``ensure_ascii`` to ``False`` in order to enable the serialization of\n    Unicode characters to UTF-8. This is easily done by using\n    :any:`functools.partial` to apply the desired keyword argument. In fact, you\n    can use this same technique to customize any option supported by the\n    ``dumps`` and ``loads`` functions::\n\n        from functools import partial\n\n        from falcon import media\n        import rapidjson\n\n        json_handler = media.JSONHandlerWS(\n            dumps=partial(\n                rapidjson.dumps,\n                ensure_ascii=False, sort_keys=True\n            ),\n        )\n\n    Keyword Arguments:\n        dumps (func): Function to use when serializing JSON.\n        loads (func): Function to use when deserializing JSON.\n    \"\"\"\n\n    __slots__ = ['dumps', 'loads']\n\n    def __init__(self, dumps=None, loads=None):\n        self._dumps = dumps or partial(json.dumps, ensure_ascii=False)\n        self._loads = loads or json.loads\n\n    def serialize(self, media: object) -> str:\n        return self._dumps(media)\n\n    def deserialize(self, payload: str) -> object:\n        return self._loads(payload)\n\n\nhttp_error._DEFAULT_JSON_HANDLER = _DEFAULT_JSON_HANDLER = JSONHandler()  # type: ignore\n", "path": "falcon/media/json.py"}]}