misc: determine a method to globally handle custom json serialization using `httpx`
Opened this issue · 2 comments
cmyui commented
At the moment, our server has a couple of locations where objects of types such as datetime
are not able to be serialized into JSON due to a lack of support in the stdlib json
module. httpx
-- the http client we use for outgoing requests, relies specifically on the stdlib json
module.
I see a couple of ways we can tackle this:
- Use
post(headers={'Content-Type': 'application/json'}, data=custom_json_dumps(...))
in each call. Never usepost(json=...)
. Seems quite error prone/duplicative. - Subclass
AsyncClient
, override thebuild_request
method, copy most fromhttpx
but use a customRequest
which overrides__init__
to perform option 1's suggestion automatically before yielding tosuper().__init__
. - Monkey-patch
httpx._content.encode_json
to provide a customJSONEncoder
subclass tojson.dumps(cls=...)
. - Implement the
httpx
maintainer's proposal tohttpx
to implement support forAsyncClient(request_class=..., response_class=...)
. Do the same__init__
override as suggested in option 1.
My preference is probably option 4 -- seems the best for the overall ecosystem. We could potentially do one of the other options in the short term as I believe this is currently having an effect on production.
cmyui commented
minisbett commented
potential hotfix:
import orjson
import httpx._content
from typing import Any, Tuple, Dict
def encode_json(json: Any) -> Tuple[Dict[str, str], httpx._content.ByteStream]:
body = orjson.dumps(json)
content_length = str(len(body))
content_type = "application/json"
headers = {"Content-Length": content_length, "Content-Type": content_type}
return headers, httpx._content.ByteStream(body)
httpx._content.encode_json = encode_json