-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Allow JSONEncoder to return bytes directly
#11989
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
base: master
Are you sure you want to change the base?
Allow JSONEncoder to return bytes directly
#11989
Conversation
Update JSONEncoder type to accept callables that return either str or bytes. This allows custom JSON serializers that directly produce bytes to be used without unnecessary decode/encode cycles. Changes: - Updated JSONEncoder type in typedefs.py to Callable[[Any], str | bytes] - Modified JsonPayload to handle both str and bytes from dumps() - Updated json_response to route bytes to body parameter, str to text - Updated WebSocketResponse.send_json to call send_bytes for bytes, send_str for str - Updated ClientWebSocketResponse.send_json with same logic This maintains full backward compatibility with existing code using json.dumps while enabling more efficient custom serializers. Fixes aio-libs#11988
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #11989 +/- ##
==========================================
- Coverage 98.75% 98.74% -0.01%
==========================================
Files 127 127
Lines 44655 44667 +12
Branches 2367 2371 +4
==========================================
+ Hits 44098 44106 +8
Misses 396 396
- Partials 161 165 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
JSONEncoder to return bytes directly
|
@bdraco Do the benchmarks already cover these cases? |
|
IIRC, there was a similar request years ago, rejected. |
|
I think it was #4482 |
webknjaz
left a comment
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.
No tests? How do we know this keeps working?
| dumps: JSONEncoder = DEFAULT_JSON_ENCODER, | ||
| ) -> None: | ||
| await self.send_str(dumps(data), compress=compress) | ||
| result = dumps(data) |
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.
Can we plz not use meaningless var names?
| @@ -0,0 +1,4 @@ | |||
| Updated the ``JSONEncoder`` type to accept callables returning either ``str`` or ``bytes``. | |||
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.
| Updated the ``JSONEncoder`` type to accept callables returning either ``str`` or ``bytes``. | |
| Updated the ``JSONEncoder`` type to accept callables returning either :data:`str` or :data:`bytes`. |
| @@ -0,0 +1,4 @@ | |||
| Updated the ``JSONEncoder`` type to accept callables returning either ``str`` or ``bytes``. | |||
| This allows a custom JSON serializer that directly produces bytes to be used with | |||
| ``ClientSession.json_serialize``, ``JsonPayload``, ``json_response``, and websocket | |||
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.
These should probably be properly linked using appropriate RST roles.
With ujson dead, I think we're ready to change this: #10795 (comment) My only question is whether the isinstance() calls here are fine, or we should add a new parameter and avoid the isinstance() checks. I suspect this is one of the performance hot paths for some cases (like websockets on homeassistant?). |
|
Ah, fair. I also had a feeling that I'd prefer having a new API rather than overloading the existing one.. |
|
Thanks for working on this! The use case makes sense. I agree with webknjaz about preferring a new API over
Alternative: Add explicit parallel methods like |
Update JSONEncoder type to accept callables that return either str or bytes.
This allows custom JSON serializers that directly produce bytes to be used
without unnecessary decode/encode cycles.
Changes
typedefs.pytoCallable[[Any], str | bytes]JsonPayloadto handle both str and bytes fromdumps()json_responseto route bytes to body parameter, str to textWebSocketResponse.send_jsonto callsend_bytesfor bytes,send_strfor strClientWebSocketResponse.send_jsonwith same logicTesting
Backward Compatibility
This maintains full backward compatibility with existing code using
json.dumpswhile enabling more efficient custom serializers.
Fixes #11988