-
-
Notifications
You must be signed in to change notification settings - Fork 842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support 'httpx.json = ...' #1352
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change footprint here sounds reasonable. :)
This won't allow per-client customization of JSON lib, which for an end user scenario doesn't sound necessary anyway, so all good.
However I'm not sure how this will play out in a stack of libraries scenario. I guess we want libraries to absolutely stay away from this knob, so that end users always remain the sole decision makers of what JSON library they want to use?
Interesting point here... The
If we're going to go for this approach we'd probably want to support either case. |
I was concerned about being able to overload each function independently because orjson returns bytes, as . I had initially thought something like this might be better:
But #1344 (comment) shows how to do it as a class. Seems reasonable to do it that way. If you wrap the |
I'd recommend cherry-picking commit 16cac58, as unneeded |
I'm sorry for that, looks like other reviewers already mentioned that, but having replaced json by I'd say you might explicitly mention that , specifying the abstract marshaller (with one default implementation which use json) Any There is another question (may be naive). Specifying active json marshaller globally, you indirectly pass this dependency to all the created clients. The question is: may it be reasonable to pass json-marshaller as an optional kwarg to an Update:
so the second question had been answered before I wrote it |
Not to be "just reject, not propose" , I created a gist with my proposal how to implement https://gist.github.com/cdeler/47dd0cc83c1fa0807aa7912cfa322f9e If you want to use your own json library, you need to inherit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great!
Some extra docs for this maybe? Happy to review those as a follow-up, but I figure we might as well add a small section to Advanced Usage
in this PR…
Just pushed some docs. Curious if anyone has any comments, otherwise I'm good with merging this. :-) |
2 typos in the second example, nothing else otherwise |
Ad-hoc solution for those of you who are waiting for this feature: import datetime
import functools
import json
try:
import pydantic
except ImportError:
pydantic = None
def _default(obj):
# For Date Time string spec, see ECMA 262
# https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
if isinstance(obj, datetime.datetime):
representation = obj.isoformat()
if representation.endswith("+00:00"):
representation = representation[:-6] + "Z"
return representation
elif pydantic and isinstance(obj, pydantic.BaseModel):
return obj.dict()
elif isinstance(obj, datetime.date):
return obj.isoformat()
elif isinstance(obj, datetime.time):
return obj.isoformat()
raise TypeError(f"Can't serialize {obj}")
def patch_httpx():
import httpx._content
httpx._content.json_dumps = functools.partial(json.dumps, default=_default)
if __name__ == '__main__':
patch_httpx()
# ... init your app here ... |
Added the 0.17 milestone for this, so we can review having it in for that (or not). |
Kind of late to the discussion, but this one aligns with my suggestion in #1362 about adding support for global configuration to httpx, e.g |
I've recently started switching over some of my codebase from requests and moving to HTTPX - only thing that's been bugging me has been the explicit calls to orjson all over the place. Is this something that's still being considered or are there no plans to merge this any time soon? Just don't want to be putting things that are too hacky into production code anytime soon so having a supported way to do this would be great. |
I don't know. I've been leaving it here because I'm not super keen on it, since it really is a sneaky little global hack. I'm also not necessarily convinced that allowing our users to switch out the JSON parsing implementation is a path we want to help folks go down, since you're making a trade-off on "various differences in edge cases of behaviour" vs. "raw parsing speed is quicker", where it's very often not the case that "quicker parsing" is actually materially important. (Because eg. you're likely actually constrained by the network in the HTTP request, rather than the JSON parsing.) I suppose having a real-world example case of "this HTTP request + JSON parsing round-trip takes X-amount-of-time if we allow support |
Unfortunately I can't give a super large amount of details, but in very generalized terms the codebase I work with passes around large amounts of data between different internal and external APIs. So any time I can save in the serialization and de-serialization of data ends up adding up pretty quick for me. That was the main reason I switched to an alternative json lib in the first place, The current solution of just manually calling orjson is fine - it would just be nicer to have something a bit cleaner. |
@tomchristie the main annoyance for me of explicitly calling orjson on my own, is that I also need to set content type. Maybe the solution should be that json accepts bytes? if it's bytes, it assumes it's an already encoded json. |
One alternate pattern that we could highlight as an option... c = httpx.Client(headers={"Content-Type": "application/json"}) Then whenever you're sending json, you'd use... r = c.post(url, content=ojson.dumps(data)) |
But then it would mark also get requests with that content type, no? |
Fair point. |
Hi! May I ask what's the status of this? We switched from Thanks! |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
I think this reasoning is a bit backwards. It's fairly hard to know where bottlenecks are going to be, and it seems clear from this discussion that nobody has actually thoroughly benchmarked this against many different possible use-cases. Given that is the case, not giving users the escape hatches they need to adjust to such bottlenecks when they find them (with their own testing) seems like poor library design. As a fairly clear example of this: the CPython FWIW I just now decided to not pick |
IMHO the biggest feature of overwriting json library isn't so much the performance it is more the flexibility. For example add the capability to dump/load Decimal (the standard lib json can do this as well with a parameter |
Closes #717
Interested to see what folks think of this.
Adds support for eg...