How-to Guide¶
Better error messages¶
Better error messages for other JSON libraries¶
>>> import json, jsonyx
>>> try:
... json.loads("[,]")
... except json.JSONDecodeError as exc:
... raise jsonyx.JSONSyntaxError(exc.msg, "<string>", exc.doc, exc.pos) from None
...
Traceback (most recent call last):
File "<string>", line 1, column 2
[,]
^
jsonyx.JSONSyntaxError: Expecting value
Better error messages for encoding strings¶
>>> import jsonyx as json
>>> try:
... "café".encode("ascii")
... except UnicodeEncodeError as exc:
... raise json.TruncatedSyntaxError(
... f"(unicode error) {exc}", "<string>", exc.object, exc.start, exc.end,
... ) from None
...
Traceback (most recent call last):
File "<string>", line 1, column 4-5
café
^
jsonyx.TruncatedSyntaxError: (unicode error) 'ascii' codec can't encode character '\xe9' in position 3: ordinal not in range(128)
Better error messages for decoding bytes¶
>>> import jsonyx as json
>>> try:
... b"caf\xe9".decode("ascii")
... except UnicodeDecodeError as exc:
... doc = exc.object.decode(exc.encoding, "replace")
... start = exc.object[:exc.start].decode(exc.encoding, "replace")
... end = exc.object[:exc.end].decode(exc.encoding, "replace")
... raise json.TruncatedSyntaxError(
... f"(unicode error) {exc}", "<string>", doc, len(start), len(end),
... ) from None
...
Traceback (most recent call last):
File "<string>", line 1, column 4-5
caf�
^
jsonyx.TruncatedSyntaxError: (unicode error) 'ascii' codec can't decode byte 0xe9 in position 3: ordinal not in range(128)
See also
jsonyx.format_syntax_error() for formatting the exception.
Encoding custom objects¶
Encoding protocol-based objects¶
Added in version 2.0.
Type |
Required methods |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
Example with numpy:
>>> import jsonyx as json
>>> import numpy as np
>>> obj = np.array([
... np.bool_(), np.int8(), np.uint8(), np.int16(), np.uint16(), np.int32(),
... np.uint32(), np.intp(), np.uintp(), np.int64(), np.uint64(), np.float16(),
... np.float32(), np.float64()
... ], dtype="O")
>>> types = {
... "array": np.ndarray,
... "bool": np.bool_,
... "float": np.floating,
... "int": np.integer
... }
>>> json.dump(obj, types=types)
[false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0, 0.0]
Note
Custom types must be registered manually, jsonyx does not
infer serializability based on method presence.
Warning
Avoid specifying ABCs for types, that is very slow.
Encoding arbitrary objects¶
Added in version 2.1.
>>> import jsonyx as json
>>> def complex_hook(obj):
... if isinstance(obj, complex):
... return {"__complex__": True, "real": obj.real, "imag": obj.imag}
... return obj
...
>>> json.dump(1 + 2j, hook=complex_hook)
{"__complex__": true, "real": 1.0, "imag": 2.0}
Tip
You can use functools.singledispatch() to make this extensible.
Warning
This function is called for every object during encoding, even if the object is normally serializable.
Decoding custom objects¶
Decoding objects using hooks¶
Added in version 2.0.
Hook |
Called with |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
Example with numpy:
>>> import jsonyx as json
>>> from functools import partial
>>> import numpy as np
>>> hooks = {
... "array": partial(np.array, dtype="O"),
... "bool": np.bool_,
... "float": np.float64,
... "int": np.int64
... }
>>> json.loads("[false, 0.0, 0]", hooks=hooks)
array([np.False_, np.float64(0.0), np.int64(0)], dtype=object)
Decoding arbitrary objects¶
>>> import jsonyx as json
>>> def object_hook(obj):
... obj = dict(obj)
... if "__complex__" in obj:
... return complex(obj["real"], obj["imag"])
... return obj
...
>>> s = '{"__complex__": true, "real": 1.0, "imag": 2.0}'
>>> json.loads(s, hooks={"object": object_hook})
(1+2j)
Warning
The "object" hook is called with a list of tuples, not a dict.
Encoding and decoding big integers¶
>>> import jsonyx as json
>>> from sys import set_int_max_str_digits
>>> set_int_max_str_digits(0)
>>> json.loads("9" * 5_000) == 10 ** 5_000 - 1
True
>>> len(json.dumps(10 ** 5_000))
5002
See Integer string conversion length limitation for more information.