connexion
connexion copied to clipboard
Use orjson instead of json for JSON serialization
Description
The authors of orjson describe it like this:
orjson is a fast, correct JSON library for Python. It benchmarks as the fastest Python library for JSON and is more correct than the standard json library or other third-party libraries.
Based on the benchmarks the authors have shared, orjson is 5 to 50 times faster than the standard json library.
Expected behaviour
Add an option to use orjson instead of json.
Actual behaviour
json is the only option for JSON serialization.
Comparing the standard Jsonifier used by Connexion and orjson in an example API call in my application, I see the difference in performance can be extreme, 570 times faster:
FlaskApi._serialize_data():
# 2434078 bytes, total time 8ms
body = orjson.dumps(data, option=orjson.OPT_NAIVE_UTC | orjson.OPT_NON_STR_KEYS)
# 3899087 bytes, total time 4565ms
body = cls.jsonifier.dumps(data)
To validate the output, I used json.loads() and verified that it creates identical objects. It does.
Please also include the option to use orjson for deserialisation.
Isn't this possible by custom json encoder? In connexion 2.x
connexion_app.app.json_encoder = CustomJSONEncoder
and by jsonifier in connexion=3.x
jsonifier=Jsonifier(kw.json)
Jsonifier unfortunately always adds JSONEncoder to dumps calls:
self.dumps_args.setdefault("cls", JSONEncoder)
which is not allowed for orjson.
You can work around this by subclassing Jsonifier:
import orjson
class OrJsonifier(Jsonifier):
"""A Jsonifier that uses orjson for serialization and deserialization."""
def dumps(self, data, **_kwargs):
return orjson.dumps(data).decode()
connexion_app = AsyncApp(name, jsonifier=OrJsonifier())
Note that the original Jsonifier adds an (unnecessary) trailing newline.