-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
orjson is significantly faster and comes with native serialization of some types like datetime or UUID.
- Loading branch information
Showing
6 changed files
with
23 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,17 @@ | ||
import json | ||
import uuid | ||
from datetime import datetime | ||
|
||
import gearman | ||
from django.utils.timezone import make_aware | ||
|
||
|
||
class JSONDecoder(json.JSONDecoder): | ||
def __init__(self, *args, **kwargs): | ||
kwargs["object_hook"] = self.object_hook | ||
super().__init__(*args, **kwargs) | ||
|
||
def object_hook(self, d: dict): | ||
object_type = d.get("__type__") | ||
if object_type == "datetime": | ||
return make_aware( | ||
datetime( | ||
d["year"], | ||
d["month"], | ||
d["day"], | ||
d["hour"], | ||
d["minute"], | ||
d["second"], | ||
d["microsecond"], | ||
) | ||
) | ||
elif object_type == "UUID": | ||
return uuid.UUID(hex=d["value"]) | ||
return d | ||
|
||
|
||
class JSONEncoder(json.JSONEncoder): | ||
def default(self, obj): | ||
if isinstance(obj, datetime): | ||
return { | ||
"__type__": "datetime", | ||
"year": obj.year, | ||
"month": obj.month, | ||
"day": obj.day, | ||
"hour": obj.hour, | ||
"minute": obj.minute, | ||
"second": obj.second, | ||
"microsecond": obj.microsecond, | ||
} | ||
elif isinstance(obj, uuid.UUID): | ||
return { | ||
"__type__": "UUID", | ||
"value": obj.hex, | ||
} | ||
else: | ||
return super().default(obj) | ||
import orjson | ||
|
||
|
||
class JSONDataEncoder(gearman.DataEncoder): | ||
"""Custom data encoder class for the `gearman` library (JSON). | ||
This class enables serialization and deserialization of data using JSON | ||
format, supporting UUID and datetime data types. | ||
""" | ||
"""Custom data encoder class for the `gearman` library (JSON).""" | ||
|
||
@classmethod | ||
def encode(cls, encodable_object): | ||
# Object of type bytes is not JSON serializable. | ||
if isinstance(encodable_object, bytes): | ||
encodable_object = encodable_object.decode("utf-8") | ||
return json.dumps(encodable_object, cls=JSONEncoder, separators=(",", ":")) | ||
return orjson.dumps(encodable_object) | ||
|
||
@classmethod | ||
def decode(cls, decodable_string): | ||
return json.loads(decodable_string, cls=JSONDecoder) | ||
return orjson.loads(decodable_string) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,17 @@ | ||
from datetime import datetime | ||
from uuid import UUID | ||
|
||
from django.utils.timezone import make_aware | ||
from gearman_encoder import JSONDataEncoder | ||
|
||
|
||
def test_json_data_encoder(): | ||
encoder = JSONDataEncoder | ||
object_py = { | ||
"id": UUID("ccf0368e-ec97-4375-a408-5c4d95c0c671"), | ||
"data": [1, 2, 3], | ||
"when": make_aware(datetime(2019, 6, 18, 1, 1, 1, 123)), | ||
} | ||
object_js = ( | ||
"{" | ||
+ '"id":{"__type__":"UUID","value":"ccf0368eec974375a4085c4d95c0c671"},' | ||
+ '"data":[1,2,3],' | ||
+ '"when":{"__type__":"datetime","year":2019,"month":6,"day":18,"hour":1,"minute":1,"second":1,"microsecond":123}}' | ||
def test_encoder(): | ||
assert JSONDataEncoder.encode(b"bytes") == b'"bytes"' | ||
assert JSONDataEncoder.encode([1, 2, 3]) == b"[1,2,3]" | ||
assert ( | ||
JSONDataEncoder.encode( | ||
{"date": make_aware(datetime(2019, 6, 18, 1, 1, 1, 123))} | ||
) | ||
== b'{"date":"2019-06-18T01:01:01.000123+00:00"}' | ||
) | ||
|
||
assert encoder.encode(object_py) == object_js | ||
assert encoder.decode(object_js) == object_py | ||
|
||
|
||
def test_json_data_encoder_with_bytes(): | ||
encoder = JSONDataEncoder | ||
|
||
assert encoder.encode(b"bytes") == '"bytes"' | ||
assert JSONDataEncoder.decode("[1,2,3]") == [1, 2, 3] |