serializejson 0.3.3__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- serializejson-0.4.0/CHANGELOG.rst +104 -0
- serializejson-0.4.0/MANIFEST.in +16 -0
- serializejson-0.4.0/PKG-INFO +519 -0
- serializejson-0.4.0/README.rst +358 -0
- serializejson-0.4.0/pyproject.toml +24 -0
- serializejson-0.4.0/rapidjson/allocators.h +692 -0
- serializejson-0.4.0/rapidjson/blosc2_determinisme.patch +198 -0
- serializejson-0.4.0/rapidjson/blosc2_headers/blosc2/blosc2-common.h +80 -0
- serializejson-0.4.0/rapidjson/blosc2_headers/blosc2/blosc2-export.h +48 -0
- serializejson-0.4.0/rapidjson/blosc2_headers/blosc2/blosc2-stdio.h +141 -0
- serializejson-0.4.0/rapidjson/blosc2_headers/blosc2.h +2911 -0
- serializejson-0.4.0/rapidjson/cursorstreamwrapper.h +78 -0
- serializejson-0.4.0/rapidjson/document.h +3043 -0
- serializejson-0.4.0/rapidjson/dtoa_repr.h +273 -0
- serializejson-0.4.0/rapidjson/eisel_lemire.h +120 -0
- serializejson-0.4.0/rapidjson/eisel_lemire_table.h +665 -0
- serializejson-0.4.0/rapidjson/encodedstream.h +299 -0
- serializejson-0.4.0/rapidjson/encodings.h +716 -0
- serializejson-0.4.0/rapidjson/error/en.h +122 -0
- serializejson-0.4.0/rapidjson/error/error.h +216 -0
- serializejson-0.4.0/rapidjson/fdwritestream.h +353 -0
- serializejson-0.4.0/rapidjson/filereadstream.h +99 -0
- serializejson-0.4.0/rapidjson/filewritestream.h +104 -0
- serializejson-0.4.0/rapidjson/fwd.h +151 -0
- serializejson-0.4.0/rapidjson/indexscan.h +993 -0
- serializejson-0.4.0/rapidjson/internal/biginteger.h +297 -0
- serializejson-0.4.0/rapidjson/internal/clzll.h +71 -0
- serializejson-0.4.0/rapidjson/internal/diyfp.h +261 -0
- serializejson-0.4.0/rapidjson/internal/dtoa.h +249 -0
- serializejson-0.4.0/rapidjson/internal/ieee754.h +78 -0
- serializejson-0.4.0/rapidjson/internal/itoa.h +308 -0
- serializejson-0.4.0/rapidjson/internal/meta.h +186 -0
- serializejson-0.4.0/rapidjson/internal/pow10.h +55 -0
- serializejson-0.4.0/rapidjson/internal/regex.h +739 -0
- serializejson-0.4.0/rapidjson/internal/stack.h +232 -0
- serializejson-0.4.0/rapidjson/internal/strfunc.h +83 -0
- serializejson-0.4.0/rapidjson/internal/strtod.h +318 -0
- serializejson-0.4.0/rapidjson/internal/swap.h +46 -0
- serializejson-0.4.0/rapidjson/istreamwrapper.h +128 -0
- serializejson-0.4.0/rapidjson/libsodium_statique.py +48 -0
- serializejson-0.4.0/rapidjson/memorybuffer.h +72 -0
- serializejson-0.4.0/rapidjson/memorystream.h +71 -0
- serializejson-0.4.0/rapidjson/msinttypes/inttypes.h +316 -0
- serializejson-0.4.0/rapidjson/msinttypes/stdint.h +300 -0
- serializejson-0.4.0/rapidjson/ostreamwrapper.h +81 -0
- serializejson-0.4.0/rapidjson/pgo_workload.py +159 -0
- serializejson-0.4.0/rapidjson/pointer.h +1482 -0
- serializejson-0.4.0/rapidjson/prettywriter.h +521 -0
- serializejson-0.4.0/rapidjson/pybytesbuffer.h +284 -0
- serializejson-0.4.0/rapidjson/pywritestreamwrapper.h +214 -0
- serializejson-0.4.0/rapidjson/rapidjson.cpp +12641 -0
- serializejson-0.4.0/rapidjson/rapidjson.h +741 -0
- serializejson-0.4.0/rapidjson/reader.h +3037 -0
- serializejson-0.4.0/rapidjson/ryu_d2d_table.h +635 -0
- serializejson-0.4.0/rapidjson/schema.h +2816 -0
- serializejson-0.4.0/rapidjson/serializejson.h +2332 -0
- serializejson-0.4.0/rapidjson/sjcrypto.h +246 -0
- serializejson-0.4.0/rapidjson/stream.h +223 -0
- serializejson-0.4.0/rapidjson/stringbuffer.h +126 -0
- serializejson-0.4.0/rapidjson/uri.h +481 -0
- serializejson-0.4.0/rapidjson/version.txt +1 -0
- serializejson-0.4.0/rapidjson/writer.h +802 -0
- serializejson-0.4.0/rapidjson/writerthread.h +967 -0
- serializejson-0.4.0/scripts/construit_libblosc2_serializejson.sh +27 -0
- serializejson-0.4.0/serializejson/__init__.py +4647 -0
- serializejson-0.4.0/serializejson/_encryption.py +362 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/image/image_conversion.py +54 -15
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/serialize/__init__.py +1 -1
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/objects.py +7 -2
- serializejson-0.4.0/serializejson/indexation.py +424 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/pickle_PyQt5_PySide2.py +30 -21
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/serializejson_PyQt5_PySide2.py +450 -251
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/serializejson_array.py +2 -6
- serializejson-0.4.0/serializejson/plugins/serializejson_builtins.py +229 -0
- serializejson-0.4.0/serializejson/plugins/serializejson_datetime.py +66 -0
- serializejson-0.4.0/serializejson/plugins/serializejson_numpy.py +438 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/tools.py +293 -28
- serializejson-0.4.0/serializejson.egg-info/PKG-INFO +519 -0
- serializejson-0.4.0/serializejson.egg-info/SOURCES.txt +102 -0
- serializejson-0.4.0/serializejson.egg-info/requires.txt +11 -0
- serializejson-0.4.0/serializejson.egg-info/top_level.txt +1 -0
- serializejson-0.4.0/setup.py +167 -0
- serializejson-0.3.3/CHANGELOG.rst +0 -39
- serializejson-0.3.3/PKG-INFO +0 -238
- serializejson-0.3.3/README.rst +0 -164
- serializejson-0.3.3/pyproject.toml +0 -9
- serializejson-0.3.3/rapidjson/rapidjson.cpp +0 -3765
- serializejson-0.3.3/serializejson/__init__.py +0 -2339
- serializejson-0.3.3/serializejson/plugins/serializejson_builtins.py +0 -141
- serializejson-0.3.3/serializejson/plugins/serializejson_datetime.py +0 -36
- serializejson-0.3.3/serializejson/plugins/serializejson_numpy.py +0 -254
- serializejson-0.3.3/serializejson.egg-info/PKG-INFO +0 -238
- serializejson-0.3.3/serializejson.egg-info/SOURCES.txt +0 -43
- serializejson-0.3.3/serializejson.egg-info/requires.txt +0 -16
- serializejson-0.3.3/serializejson.egg-info/top_level.txt +0 -3
- serializejson-0.3.3/setup.py +0 -107
- serializejson-0.3.3/tests/test_iterator.py +0 -21
- serializejson-0.3.3/tests/test_serialize_vs_pickle.py +0 -600
- {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE-APACHE.rst +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE-PATRON.rst +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE-PROSPERITY.rst +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE.rst +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/__init__.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/files/__init__.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/image/__init__.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/string/__init__.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/string/encodings/__init__.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/string/encodings/ascii_printables.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/__init__.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/dictionaries.py +0 -0
- {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/functions.py +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/__init__.py +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/module_name.py +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/serialize_parameters.py +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/simple_exemple.py +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/simple_exemple_update.py +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson.egg-info/dependency_links.txt +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/serializejson.egg-info/not-zip-safe +0 -0
- {serializejson-0.3.3 → serializejson-0.4.0}/setup.cfg +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Version 0.4.0
|
|
2
|
+
-------------
|
|
3
|
+
:Date: 2026-10-02
|
|
4
|
+
|
|
5
|
+
* optional authenticated encryption: ``encryption_key="password"`` on
|
|
6
|
+
``dump``/``dumps``/``dumpb``/``load``/``loads``/``Encoder``/``Decoder``
|
|
7
|
+
writes and reads standard `age <https://age-encryption.org>`_ v1 files
|
|
8
|
+
(scrypt passphrase, ChaCha20-Poly1305), decryptable by any age tool; any
|
|
9
|
+
modified byte or wrong password raises ``DecryptionError``; ``dumps``
|
|
10
|
+
returns the ASCII armored form, ``encryption_in_base64=True`` forces it
|
|
11
|
+
everywhere (bytes, files) and ``False`` forces the binary form; no extra
|
|
12
|
+
package: libsodium 1.0.22 is linked into the C extension (built from the
|
|
13
|
+
pinned ``libsodium/`` clone), payload segments spread over all cores
|
|
14
|
+
* WebAssembly wheel for Pyodide (``scripts/construit_wasm.sh``): runs in the
|
|
15
|
+
browser, encryption included, through the same linked libsodium
|
|
16
|
+
* position index: ``load(file, path="root['a'][0].b")`` reads one object of a
|
|
17
|
+
json file without parsing the rest, ``serializejson.index()`` indexes a file
|
|
18
|
+
already written and ``serializejson.paths()`` lists what it holds
|
|
19
|
+
* ``dump`` to a named file now writes that index by default, zstd compressed
|
|
20
|
+
in a hidden sidecar file of the same name preceded by a dot, which leaves
|
|
21
|
+
the json itself standard (``index="comment"`` appends it to the json as a
|
|
22
|
+
comment line instead — one single file to move, but no other parser reads it
|
|
23
|
+
any more; ``index=None`` writes none); files whose containers all stay under
|
|
24
|
+
``index_threshold`` keep no index at all
|
|
25
|
+
* Python 3.11 to 3.14 support (default ``object.__getstate__`` handled), numpy 2 support
|
|
26
|
+
* circular references and duplicates now handled for lists and dicts too (``$ref``),
|
|
27
|
+
including physically shared ``__dict__`` (restored at load, beyond pickle)
|
|
28
|
+
* big speedups: per-class fast paths fully in C++ (encode and decode),
|
|
29
|
+
SIMD parser, base64 written/read without intermediate strings,
|
|
30
|
+
readable numpy arrays written straight from their buffer (``ArrayRows``)
|
|
31
|
+
* blosc2 compression in C without Python round trip; DETERMINISTIC internal
|
|
32
|
+
multithreading via the bundled patched libblosc2 (same bytes whatever the
|
|
33
|
+
thread count); parallel base64; chunked parallel fallback (``b64_blosc2p``)
|
|
34
|
+
* default compression switched to ``blosc2_zstd`` (old ``b64_blosc`` files
|
|
35
|
+
still readable; new files need a blosc2-capable serializejson)
|
|
36
|
+
* homogeneous number lists written on a single line everywhere (dict values,
|
|
37
|
+
nested lists), decided in C++
|
|
38
|
+
* fixes: segfault on 3.12/3.13 with deep/cyclic data, ``append()`` of objects,
|
|
39
|
+
float subclasses written via ``repr()`` (numpy 2), docstring SyntaxWarnings
|
|
40
|
+
* reading rebuilds objects as the parse goes (``rehydrate=True``, the new
|
|
41
|
+
default): each instance is built as soon as its envelope is read, and with
|
|
42
|
+
``obj=`` the live objects are adopted in place (identities kept, arguments
|
|
43
|
+
reconciled one by one) instead of a dict tree then a second pass;
|
|
44
|
+
``rehydrate=False`` restores the previous behaviour
|
|
45
|
+
* Qt: signal/slot connections serialized by introspection (PySide6), whole
|
|
46
|
+
widget trees with ``qt_tree=True``, QTimer/QAction state, PySide6 enums;
|
|
47
|
+
``qtpy6`` replaces ``qtpy`` (PySide6 by default); QImage rows with a stride
|
|
48
|
+
not multiple of 4 bytes are no longer shifted
|
|
49
|
+
* ``datetime.datetime`` written as RFC 9557 text (``isoformat()``, plus
|
|
50
|
+
``[Zone/Name]`` for ``ZoneInfo``, which was not serializable before); the
|
|
51
|
+
former reduce forms are still read
|
|
52
|
+
* ``etat_sans_defauts(obj, defaults, properties)``: C helper building the flat
|
|
53
|
+
state of an object without its default values, for ``__serializejson__``
|
|
54
|
+
hooks written by applications
|
|
55
|
+
* classes with ``__setstate__`` are decoded in C with a single
|
|
56
|
+
``__setstate__`` call (-30 % on such objects, -43 % on a deep document of
|
|
57
|
+
452 objects), as are classes whose name is shortened by the application
|
|
58
|
+
|
|
59
|
+
Version 0.3.4
|
|
60
|
+
-------------
|
|
61
|
+
:Date: 2023-06-11
|
|
62
|
+
|
|
63
|
+
* Restore ducumentation
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
Version 0.3.3
|
|
67
|
+
-------------
|
|
68
|
+
:Date: 2022-10-18
|
|
69
|
+
|
|
70
|
+
* Big speed improvement for bytes and numpy array serialization
|
|
71
|
+
|
|
72
|
+
Version 0.3.2
|
|
73
|
+
-------------
|
|
74
|
+
:Date: 2022-10-01
|
|
75
|
+
|
|
76
|
+
* API changed
|
|
77
|
+
* add better support for cicular reférences and duplicates with {"$ref": ...}
|
|
78
|
+
|
|
79
|
+
Version 0.2.0
|
|
80
|
+
-------------
|
|
81
|
+
:Date: 2021-02-18
|
|
82
|
+
|
|
83
|
+
* API changed
|
|
84
|
+
* can serialize dict with no-string keys
|
|
85
|
+
* add support for cicular reférences and duplicates with {"$ref": ...}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
Version 0.1.0
|
|
89
|
+
-------------
|
|
90
|
+
:Date: 2020-11-28
|
|
91
|
+
|
|
92
|
+
* change description for pipy
|
|
93
|
+
* add license for pipy
|
|
94
|
+
* enable load of tuple, time.struct_time, Counter, OrderedDict and defaultdict
|
|
95
|
+
|
|
96
|
+
Version 0.0.4
|
|
97
|
+
-------------
|
|
98
|
+
:Date: 2020-11-24
|
|
99
|
+
|
|
100
|
+
* API changed
|
|
101
|
+
* add plugins support
|
|
102
|
+
* add bytes, bytearray and numpy.array compression with blosc zstd
|
|
103
|
+
* fix itertive append and decode (not fully tested).
|
|
104
|
+
* fix dump of numpy types without conversion to python types(not yet numpy.float64)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# sdist : de quoi reconstruire le module compilé et sa libblosc2 depuis les sources
|
|
2
|
+
include CHANGELOG.rst LICENSE*.rst README.rst
|
|
3
|
+
include rapidjson/version.txt rapidjson/blosc2_determinisme.patch rapidjson/pgo_workload.py rapidjson/libsodium_statique.py
|
|
4
|
+
recursive-include rapidjson *.h
|
|
5
|
+
include scripts/construit_libblosc2_serializejson.sh
|
|
6
|
+
# construits sur la machine de développement, jamais distribués
|
|
7
|
+
global-exclude *.so
|
|
8
|
+
# un greffon de fichiers git (setuptools_scm) ajouterait tout le dépôt :
|
|
9
|
+
# ces dossiers ne servent ni à construire ni à utiliser le paquet
|
|
10
|
+
prune Notes
|
|
11
|
+
prune images_benchmarks
|
|
12
|
+
prune docs
|
|
13
|
+
prune docs_source
|
|
14
|
+
prune tests
|
|
15
|
+
prune .github
|
|
16
|
+
exclude my_list.json requirements.txt Makefile make.bat CLAUDE.md .directory .hgignore .ignore
|
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: serializejson
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: A python library for fast serialization and deserialization of complex Python objects into JSON.
|
|
5
|
+
Home-page: https://github.com/SmartAudioTools/serializejson
|
|
6
|
+
Author: Baptiste de La Gorce
|
|
7
|
+
Author-email: baptiste.delagorce@smartaudiotools.com
|
|
8
|
+
License: Prosperity Public License 3.0.0 and Patron License 1.0.0
|
|
9
|
+
Project-URL: Documentation, https://smartaudiotools.github.io/serializejson
|
|
10
|
+
Project-URL: Funding, https://github.com/sponsors/SmartAudioTools
|
|
11
|
+
Project-URL: Source, https://github.com/SmartAudioTools/serializejson
|
|
12
|
+
Project-URL: Tracker, https://github.com/SmartAudioTools/serializejson/issues
|
|
13
|
+
Keywords: pickle json serialize dump dumps rapidjson base64
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: Free for non-commercial use
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: C++
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/x-rst
|
|
27
|
+
License-File: LICENSE-APACHE.rst
|
|
28
|
+
License-File: LICENSE-PATRON.rst
|
|
29
|
+
License-File: LICENSE-PROSPERITY.rst
|
|
30
|
+
License-File: LICENSE.rst
|
|
31
|
+
Requires-Dist: apply
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest; extra == "dev"
|
|
34
|
+
Requires-Dist: numpy; extra == "dev"
|
|
35
|
+
Requires-Dist: qtpy6; extra == "dev"
|
|
36
|
+
Requires-Dist: PySide6; extra == "dev"
|
|
37
|
+
Provides-Extra: test
|
|
38
|
+
Requires-Dist: pytest; extra == "test"
|
|
39
|
+
Requires-Dist: numpy; extra == "test"
|
|
40
|
+
Dynamic: author
|
|
41
|
+
Dynamic: author-email
|
|
42
|
+
Dynamic: classifier
|
|
43
|
+
Dynamic: description
|
|
44
|
+
Dynamic: description-content-type
|
|
45
|
+
Dynamic: home-page
|
|
46
|
+
Dynamic: keywords
|
|
47
|
+
Dynamic: license
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
Dynamic: project-url
|
|
50
|
+
Dynamic: provides-extra
|
|
51
|
+
Dynamic: requires-dist
|
|
52
|
+
Dynamic: requires-python
|
|
53
|
+
Dynamic: summary
|
|
54
|
+
|
|
55
|
+
serializejson
|
|
56
|
+
=============
|
|
57
|
+
|
|
58
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
59
|
+
| **Authors** | `Baptiste de La Gorce <contact@smartaudiotools.com>`_ |
|
|
60
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
61
|
+
| **PyPI** | https://pypi.org/project/serializejson |
|
|
62
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
63
|
+
| **Documentation** | https://smartaudiotools.github.io/serializejson |
|
|
64
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
65
|
+
| **Sources** | https://github.com/SmartAudioTools/serializejson |
|
|
66
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
67
|
+
| **Issues** | https://github.com/SmartAudioTools/serializejson/issues |
|
|
68
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
69
|
+
| **Noncommercial license** | `Prosperity Public License 3.0.0 <https://github.com/SmartAudioTools/serializejson/blob/master/LICENSE-PROSPERITY.rst>`_ |
|
|
70
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
71
|
+
| **Commercial license** | `Patron License 1.0.0 <https://github.com/SmartAudioTools/serializejson/blob/master/LICENSE-PATRON.rst>`_ |
|
|
72
|
+
| | ⇒ `Sponsor me ! <https://github.com/sponsors/SmartAudioTools>`_ or `contact me ! <contact@smartaudiotools.com>`_ |
|
|
73
|
+
+---------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
**serializejson** is a python library for fast serialization and deserialization
|
|
77
|
+
of python objects in `JSON <http://json.org>`_ designed as a safe, interoperable and human-readable drop-in replacement for the Python `pickle <https://docs.python.org/3/library/pickle.html>`_ package.
|
|
78
|
+
Complex python object hierarchies are serializable, deserializable or updatable in once, allowing for example to save or restore a complete application state in few lines of code.
|
|
79
|
+
The library is built upon a C++ extension derived from
|
|
80
|
+
`python-rapidjson <https://github.com/python-rapidjson/python-rapidjson>`_, with
|
|
81
|
+
`c-blosc2 <https://github.com/Blosc/c-blosc2>`_ bundled for optional lossless compression (lz4, `zstandard <https://github.com/facebook/zstd>`_).
|
|
82
|
+
Binary wheels are provided for Linux x86_64, CPython 3.10 to 3.14.
|
|
83
|
+
|
|
84
|
+
Some of the main features:
|
|
85
|
+
|
|
86
|
+
- supports Python 3.10 or greater (tested on 3.10 to 3.14).
|
|
87
|
+
- serializes arbitrary python objects into a dictionary by adding `__class__` ,and eventually `__init__`, `__new__`, `__state__`, `__items__` keys.
|
|
88
|
+
- calls the same objects methods as pickle. Therefore almost all pickable objects are serializable with serializejson without any modification.
|
|
89
|
+
- for not already pickable object, you will allways be able to serialize it by adding methodes to the object or creating plugins for pickle or serializejson.
|
|
90
|
+
- fast: builtin types, envelopes of common classes (datetime, Decimal, sets, tuples, collections…) and ``__setstate__`` / ``__reduce__`` objects are written and read in C++ without python callbacks. Most types stay within 2x of pickle, some are faster (datetime and Decimal writing, str and lists reading); see the benchmarks below.
|
|
91
|
+
- serializes and deserializes bytes and bytearray very quickly in base64, encoded and decoded in C++ directly from and into the JSON stream, with lossless `c-blosc2 <https://github.com/Blosc/c-blosc2>`_ compression; when dumping to a file, compression runs in a background writer thread.
|
|
92
|
+
- serialize properties and attributes with getters and setters if wanted (unlike pickle).
|
|
93
|
+
- json data will still be directly loadable if you have transform some attributes in slots or properties in your code since your last serialization. (unlike pickle)
|
|
94
|
+
- can serialize `__init__(self,..)` arguments by name instead of positions, allowing to skip arguments with defauts values and making json datas robust to a change of `__init__` parameters order.
|
|
95
|
+
- serialized objects take generally less space than when serialized with pickle: for binary data, the 30% increase due to base64 encoding is in general largely compensated using the lossless `c-blosc2 <https://github.com/Blosc/c-blosc2>`_ compression, whose ``bytes_compression="smart"`` ladder trades size for speed by a single level number, from the fast default up to 59 % of pickle's size (see the benchmarks below).
|
|
96
|
+
- serialized objects are human-readable and easy to read. Unlike pickled data, your data will never become unreadable if your code evolves: you will always be able to modify your datas with a text editor (with find & replace for example if you change an attribut name).
|
|
97
|
+
- serialized objects are text and therefore versionable and comparable with versionning and comparaison tools.
|
|
98
|
+
- can safely load untrusted / unauthenticated sources if authorized_classes list parameter is set carefully with strictly necessary objects (unlike pickle).
|
|
99
|
+
- rebuilds objects as the parse goes (``rehydrate=True``, the default): with ``obj=``, existing objects are updated recursively in place instead of being replaced (identities kept, constructor arguments reconciled one by one), which allows to save and restore a complete application state, Qt widgets included.
|
|
100
|
+
- Qt (PySide6 by default through ``qtpy6``): signal/slot connections, whole widget trees (``qt_tree=True``), QTimer/QAction state, enums and QImage are serializable.
|
|
101
|
+
- ``datetime.datetime`` is written as readable `RFC 9557 <https://www.rfc-editor.org/rfc/rfc9557>`_ text (``"2026-10-02T16:30:00+02:00[Europe/Paris]"``), ``ZoneInfo`` time zones included.
|
|
102
|
+
- filters attribute starting with "_" by default (unlike pickle). You can keep them if wanted with `filter_ = False`.
|
|
103
|
+
- numpy arrays can be serialized as lists with automatic conversion in both ways or in a conservative way.
|
|
104
|
+
- supports circular references and serialize only once duplicated objects, lists and dictionaries, using "$ref" key an path to the first occurance in the json : `{"$ref": "root.xxx.elt"}`.
|
|
105
|
+
- accepts json with comment (// and /\* \*/) if `accept_comments = True`.
|
|
106
|
+
- can automatically recognize objects in json from keys names and recreate them, without the need of `__class__` key, if passed in `recognized_classes`.
|
|
107
|
+
- serializejson is easly interoperable outside of the Python ecosystem with this recognition of objects from keys names or with `__class__` translation between python and other language classes.
|
|
108
|
+
- dump and load support string path.
|
|
109
|
+
- can iteratively encode (with append) and decode (with iterator) a list in json file, which helps saving memory space during the process of serialization and deserialization and useful for logs.
|
|
110
|
+
- can write a position index beside the json (``index="sidecar"``) or at its end (``index="comment"``), and then load a single object from its path — ``load("base.json", path="root['clients'][3].name")`` — without parsing the rest of the document.
|
|
111
|
+
- can encrypt with a password (``encryption_key="…"``) in the standard `age <https://age-encryption.org>`_ format, as binary or as ASCII armor (``encryption_in_base64``).
|
|
112
|
+
- runs in the browser under `Pyodide <https://pyodide.org>`_ (WebAssembly wheel), encryption included.
|
|
113
|
+
|
|
114
|
+
.. warning::
|
|
115
|
+
|
|
116
|
+
**⚠** Do not load serializejson files from untrusted / unauthenticated sources without carefully setting the load authorized_classes parameter.
|
|
117
|
+
|
|
118
|
+
**⚠** Never dump a dictionary with the `__class__` key, otherwise serializejson will attempt to reconstruct an object when loading the json.
|
|
119
|
+
Be careful not to allow a user to manually enter a dictionary key somewhere without checking that it is not `__class__`.
|
|
120
|
+
Due to current limitation of rapidjson we cannot we cannot at the moment efficiently detect dictionaries with the `__class__` key to raise an error.
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
Benchmarks against pickle
|
|
124
|
+
=========================
|
|
125
|
+
|
|
126
|
+
All charts below compare serializejson **with its default settings** (level 1
|
|
127
|
+
of the ``bytes_compression="smart"`` ladder: zigzag → bitshuffle → lz4 level
|
|
128
|
+
1, base64 and JSON envelope **included**) against ``pickle.dumps``
|
|
129
|
+
protocol 4, on REAL corpora (photographic and screenshot images, SQAM audio
|
|
130
|
+
references, and the whole set concatenated into a single 200 MB array as the
|
|
131
|
+
out-of-cache case).
|
|
132
|
+
Every value is a ratio serializejson / pickle: **below ×1 — the smaller the
|
|
133
|
+
bar, the bigger the advantage for serializejson**. They are produced by
|
|
134
|
+
``python tests/lance_benchmarks.py`` (median of ~50 trials, alternated in
|
|
135
|
+
the same process, **cache flushed before each trial** — the RAM regime is the
|
|
136
|
+
only one a real application gets on data it has just produced).
|
|
137
|
+
|
|
138
|
+
Pure in-memory conversion — with the **default** level 1 the serialized size is
|
|
139
|
+
**82 % of pickle's on geometric average** (up to 1.5× smaller on audio, but
|
|
140
|
+
14 to 24 % *larger* on the most photographic images, which no generic chain
|
|
141
|
+
compresses), and the whole ladder is one number away: its **last level brings
|
|
142
|
+
that to 59 %** of pickle's size, for about a quarter more CPU time. Pickle,
|
|
143
|
+
which is a simple memory copy, stays faster on CPU time alone in every case.
|
|
144
|
+
Every chart uses the same device: four time bars — writing then reading back,
|
|
145
|
+
first in RAM, then to and from the measuring machine's disk (NVMe PCIe 3,
|
|
146
|
+
~3.5 GB/s, transfer time included) — under an unfilled **blue frame whose top
|
|
147
|
+
edge is the size ratio**, as wide as the four bars together, so nothing is ever
|
|
148
|
+
hidden. One chart per ladder setting, since the size depends neither on the
|
|
149
|
+
direction nor on the device. The vertical scale is linear below ×1 and logarithmic
|
|
150
|
+
above it. The three charts are the default level, the smallest level of the
|
|
151
|
+
ladder, and its level 0, which drops compression altogether (plain base64) —
|
|
152
|
+
writing then becomes **faster than pickle** on most profiles, at the cost of a
|
|
153
|
+
payload one third larger:
|
|
154
|
+
|
|
155
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_memoire_smart.svg
|
|
156
|
+
:alt: default smart level: size and speed ratios against pickle
|
|
157
|
+
:width: 100%
|
|
158
|
+
|
|
159
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_memoire_min.svg
|
|
160
|
+
:alt: smallest smart level: size and speed ratios against pickle
|
|
161
|
+
:width: 100%
|
|
162
|
+
|
|
163
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_memoire_b64.svg
|
|
164
|
+
:alt: no compression at all: size and speed ratios against pickle
|
|
165
|
+
:width: 100%
|
|
166
|
+
|
|
167
|
+
As soon as the bytes have to reach a storage device or a network, the saved
|
|
168
|
+
bytes also save time: the curves below show the **total** time ratio
|
|
169
|
+
(serialization + transfer at the given throughput). At the default level, the
|
|
170
|
+
break-even throughput is around 700 MB/s to 1.4 GB/s on the audio corpora and
|
|
171
|
+
below 500 MB/s on the images, so serializejson wins on a hard drive and on a
|
|
172
|
+
SATA SSD for everything that compresses, while pickle keeps the lead on a fast
|
|
173
|
+
NVMe and on data that does not compress:
|
|
174
|
+
|
|
175
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_ecriture_support.svg
|
|
176
|
+
:alt: total write time ratio against storage throughput
|
|
177
|
+
:width: 100%
|
|
178
|
+
|
|
179
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_lecture_support.svg
|
|
180
|
+
:alt: total read time ratio against storage throughput
|
|
181
|
+
:width: 100%
|
|
182
|
+
|
|
183
|
+
On realistic machines — pairing each CPU with a storage of the same class,
|
|
184
|
+
from a Raspberry Pi 5 on a microSD (or on an NVMe capped by its single
|
|
185
|
+
PCIe 2.0 lane) to a Ryzen 9 desktop on a PCIe 5 NVMe — the balance follows
|
|
186
|
+
the storage: the slower it is, the more the saved bytes pay back the compute
|
|
187
|
+
time. On the anchor profile, a screenshot corpus that barely compresses (96 %
|
|
188
|
+
of pickle's size at the default level), pickle stays ahead everywhere, from
|
|
189
|
+
×1.07 on the microSD Pi to ×2.64 on the PCIe 5 desktop — the slow machine is
|
|
190
|
+
where the gap almost closes, and a level of the ladder that actually shrinks
|
|
191
|
+
the payload turns it around. The chart is anchored on the corpus's largest
|
|
192
|
+
single profile, named in its title, with compute times scaled by each CPU's
|
|
193
|
+
approximate relative speed:
|
|
194
|
+
|
|
195
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_machines.svg
|
|
196
|
+
:alt: total write and read time ratios on realistic machines
|
|
197
|
+
:width: 100%
|
|
198
|
+
|
|
199
|
+
Against dedicated lossless image codecs on the image corpora, serializejson
|
|
200
|
+
does not predict in 2D so PNG compresses 1.6-2.2× smaller and lossless
|
|
201
|
+
JPEG XL 1.8-3.3× smaller — but the default level **encodes more than 20×
|
|
202
|
+
faster than both**, and decodes 8 to 10× faster than PNG (27 to 70× faster
|
|
203
|
+
than JPEG XL, whose times include the process launch):
|
|
204
|
+
|
|
205
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_codecs_images.svg
|
|
206
|
+
:alt: serializejson against PNG and JPEG XL on the image corpora
|
|
207
|
+
:width: 100%
|
|
208
|
+
|
|
209
|
+
The next two charts put each codec in the usual device — size frame over the
|
|
210
|
+
four time bars — with the codec, not pickle, as the reference:
|
|
211
|
+
|
|
212
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_codecs_png.svg
|
|
213
|
+
:alt: serializejson against PNG: size and time ratios
|
|
214
|
+
:width: 100%
|
|
215
|
+
|
|
216
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_codecs_jxl.svg
|
|
217
|
+
:alt: serializejson against lossless JPEG XL: size and time ratios
|
|
218
|
+
:width: 100%
|
|
219
|
+
|
|
220
|
+
Beyond big binary data, the repository's object catalog (every python type
|
|
221
|
+
category from ``tests/objects/basic_objects.py``) and the official
|
|
222
|
+
pyperformance ``bm_pickle`` workloads (myriads of small dicts, tuples and
|
|
223
|
+
lists — pickle's historical home turf) give the honest picture on small
|
|
224
|
+
objects: serializejson stays within ×1.3-2.0 of pickle when writing and
|
|
225
|
+
×1.4-2.4 when reading on the official workloads, with a few identified slow
|
|
226
|
+
paths on exotic categories. At those
|
|
227
|
+
sizes RAM and cache are not distinguishable — a few kilobytes stay in cache in
|
|
228
|
+
real life too — so the first two bars are cache times and the disk bars add
|
|
229
|
+
almost nothing:
|
|
230
|
+
|
|
231
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_types_objets.svg
|
|
232
|
+
:alt: time ratios per python type category
|
|
233
|
+
:width: 100%
|
|
234
|
+
|
|
235
|
+
.. image:: https://raw.githubusercontent.com/SmartAudioTools/serializejson/master/docs_source/images/benchmark_pyperformance.svg
|
|
236
|
+
:alt: time ratios on the official pyperformance pickle workloads
|
|
237
|
+
:width: 100%
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
Installation
|
|
241
|
+
============
|
|
242
|
+
|
|
243
|
+
**Last offical release**
|
|
244
|
+
|
|
245
|
+
.. code-block::
|
|
246
|
+
|
|
247
|
+
pip install serializejson
|
|
248
|
+
|
|
249
|
+
**Developpement version unreleased**
|
|
250
|
+
|
|
251
|
+
.. code-block::
|
|
252
|
+
|
|
253
|
+
pip install git+https://github.com/SmartAudioTools/serializejson.git
|
|
254
|
+
|
|
255
|
+
Examples
|
|
256
|
+
================
|
|
257
|
+
|
|
258
|
+
**Serialization with fonctions API**
|
|
259
|
+
|
|
260
|
+
.. code-block:: python
|
|
261
|
+
|
|
262
|
+
import serializejson
|
|
263
|
+
|
|
264
|
+
# serialize in string
|
|
265
|
+
object1 = set([1,2])
|
|
266
|
+
dumped1 = serializejson.dumps(object1)
|
|
267
|
+
loaded1 = serializejson.loads(dumped1)
|
|
268
|
+
print(dumped1)
|
|
269
|
+
>{
|
|
270
|
+
> "__class__": "set",
|
|
271
|
+
> "__init__": [1,2]
|
|
272
|
+
>}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# serialize in file
|
|
276
|
+
object2 = set([3,4])
|
|
277
|
+
serializejson.dump(object2,"dumped2.json")
|
|
278
|
+
loaded2 = serializejson.load("dumped2.json")
|
|
279
|
+
|
|
280
|
+
**Serialization with classes based API.**
|
|
281
|
+
|
|
282
|
+
.. code-block:: python
|
|
283
|
+
|
|
284
|
+
import serializejson
|
|
285
|
+
encoder = serializejson.Encoder()
|
|
286
|
+
decoder = serializejson.Decoder()
|
|
287
|
+
|
|
288
|
+
# serialize in string
|
|
289
|
+
|
|
290
|
+
object1 = set([1,2])
|
|
291
|
+
dumped1 = encoder.dumps(object1)
|
|
292
|
+
loaded1 = decoder.loads(dumped1)
|
|
293
|
+
print(dumped1)
|
|
294
|
+
|
|
295
|
+
# serialize in file
|
|
296
|
+
object2 = set([3,4])
|
|
297
|
+
encoder.dump(object2,"dumped2.json")
|
|
298
|
+
loaded2 = decoder.load("dumped2.json")
|
|
299
|
+
|
|
300
|
+
**Update existing object**
|
|
301
|
+
|
|
302
|
+
.. code-block:: python
|
|
303
|
+
|
|
304
|
+
import serializejson
|
|
305
|
+
object1 = set([1,2])
|
|
306
|
+
object2 = set([3,4])
|
|
307
|
+
dumped1 = serializejson.dumps(object1)
|
|
308
|
+
print(f"id {id(object2)} : {object2}")
|
|
309
|
+
serializejson.loads(dumped1,obj = object2, updatables_classes = [set])
|
|
310
|
+
print(f"id {id(object2)} : {object2}")
|
|
311
|
+
|
|
312
|
+
**Iterative serialization and deserialization**
|
|
313
|
+
|
|
314
|
+
.. code-block:: python
|
|
315
|
+
|
|
316
|
+
import serializejson
|
|
317
|
+
encoder = serializejson.Encoder("my_list.json",indent = None)
|
|
318
|
+
for elt in range(3):
|
|
319
|
+
encoder.append(elt)
|
|
320
|
+
print(open("my_list.json").read())
|
|
321
|
+
for elt in serializejson.Decoder("my_list.json"):
|
|
322
|
+
print(elt)
|
|
323
|
+
>[0,1,2]
|
|
324
|
+
>0
|
|
325
|
+
>1
|
|
326
|
+
>2
|
|
327
|
+
|
|
328
|
+
**Load one object from a big json, without reading the rest**
|
|
329
|
+
|
|
330
|
+
.. code-block:: python
|
|
331
|
+
|
|
332
|
+
import serializejson
|
|
333
|
+
|
|
334
|
+
class Client:
|
|
335
|
+
def __init__(self, name=None):
|
|
336
|
+
self.name = name
|
|
337
|
+
|
|
338
|
+
base = {"clients": [Client("c%d" % i) for i in range(1000)]}
|
|
339
|
+
|
|
340
|
+
# write the json together with its position index
|
|
341
|
+
serializejson.dump(base, "base.json", index="sidecar", index_threshold=32)
|
|
342
|
+
|
|
343
|
+
# ... or index a json file that already exists
|
|
344
|
+
serializejson.index("base.json", threshold=32)
|
|
345
|
+
print(serializejson.paths("base.json")) # what the index knows
|
|
346
|
+
|
|
347
|
+
# then load only what is wanted, with the `$ref` path grammar
|
|
348
|
+
client = serializejson.load("base.json", path="root['clients'][3]")
|
|
349
|
+
name = serializejson.load("base.json", path="root['clients'][3].name")
|
|
350
|
+
|
|
351
|
+
The path always gives what a full load would give: references shared with the
|
|
352
|
+
rest of the document are followed, and a cycle simply falls back to reading
|
|
353
|
+
the whole file. A path that is not in the index is served by its nearest
|
|
354
|
+
indexed ancestor, and a file without any index still answers — only the time
|
|
355
|
+
changes.
|
|
356
|
+
|
|
357
|
+
Two ways of storing the index, to be chosen by use:
|
|
358
|
+
|
|
359
|
+
- ``index="sidecar"`` writes a hidden file of the same name preceded by a dot.
|
|
360
|
+
The json itself stays **standard**, readable by any other parser, but the
|
|
361
|
+
index is a second file to copy and move along.
|
|
362
|
+
- ``index="comment"`` appends two comment lines at the end of the json. One
|
|
363
|
+
single file, but the document is **no longer standard json** — other parsers
|
|
364
|
+
reject it (serializejson reads it back without trouble).
|
|
365
|
+
|
|
366
|
+
Both cost the same to build and to use. On a 5.9 MB document of 50 objects
|
|
367
|
+
(measured on the reference machine, Python 3.12): the index weighs 4.7 KB
|
|
368
|
+
(0.08 %), loading one object takes 0.26 ms against 7.4 ms for the whole
|
|
369
|
+
document (×28), and 0.03 ms for a lone attribute. The price is at writing
|
|
370
|
+
time: the index is built by scanning the produced json at about 30 MB/s, here
|
|
371
|
+
198 ms against 6.3 ms to write the file — nothing is paid when the index is
|
|
372
|
+
not asked for. ``index_threshold`` (1024 bytes by default) is the lever:
|
|
373
|
+
containers smaller than that are not indexed, which keeps the index marginal
|
|
374
|
+
but leaves small objects to be reached through their ancestor.
|
|
375
|
+
|
|
376
|
+
**Encryption with a password**
|
|
377
|
+
|
|
378
|
+
``encryption_key`` encrypts in the `age <https://age-encryption.org>`_ v1
|
|
379
|
+
format (scrypt + ChaCha20-Poly1305), checked against age's official test
|
|
380
|
+
vectors: the file opens with ``age --decrypt`` as well. No extra package:
|
|
381
|
+
libsodium is linked into the C extension, the same on every platform.
|
|
382
|
+
|
|
383
|
+
.. code-block:: python
|
|
384
|
+
|
|
385
|
+
serializejson.dump(state, "state.json", encryption_key="secret")
|
|
386
|
+
state = serializejson.load("state.json", encryption_key="secret")
|
|
387
|
+
|
|
388
|
+
``encryption_in_base64`` chooses between the binary form and the ASCII armor
|
|
389
|
+
(base64 between ``-----BEGIN AGE ENCRYPTED FILE-----`` lines). By default
|
|
390
|
+
(``None``) ``dumps`` returns the armor, since its result is text, and files and
|
|
391
|
+
bytes stay binary, a third shorter; ``True`` forces the armor everywhere,
|
|
392
|
+
``False`` the binary form. Loading recognizes both forms by itself.
|
|
393
|
+
|
|
394
|
+
**In the browser (Pyodide)**
|
|
395
|
+
|
|
396
|
+
A WebAssembly wheel (``scripts/construit_wasm.sh``) is loaded by
|
|
397
|
+
``pyodide.loadPackage``. Encryption works there too, through the same
|
|
398
|
+
libsodium linked into the extension.
|
|
399
|
+
|
|
400
|
+
More examples and complete documentation `here <https://smartaudiotools.github.io/serializejson/>`_
|
|
401
|
+
|
|
402
|
+
License
|
|
403
|
+
=======
|
|
404
|
+
|
|
405
|
+
Copyright 2020 Baptiste de La Gorce
|
|
406
|
+
|
|
407
|
+
For noncommercial use or thirty-day limited free-trial period commercial use, this project is licensed under the `Prosperity Public License 3.0.0 <https://github.com/SmartAudioTools/serializejson/blob/master/LICENSE-PROSPERITY.rst>`_.
|
|
408
|
+
|
|
409
|
+
For non limited commercial use, this project is licensed under the `Patron License 1.0.0 <https://github.com/SmartAudioTools/serializejson/blob/master/LICENSE-PATRON.rst>`_.
|
|
410
|
+
To acquire a license please `contact me <mailto:contact@smartaudiotools.com>`_, or just `sponsor me on GitHub <https://github.com/sponsors/SmartAudioTools>`_ under the appropriate tier ! This funding model helps me making my work sustainable and compensates me for the work it took to write this crate!
|
|
411
|
+
|
|
412
|
+
Third-party contributions are licensed under `Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0>`_ and belong to their respective authors.
|
|
413
|
+
History
|
|
414
|
+
=======
|
|
415
|
+
|
|
416
|
+
Version 0.4.0
|
|
417
|
+
-------------
|
|
418
|
+
:Date: 2026-10-02
|
|
419
|
+
|
|
420
|
+
* optional authenticated encryption: ``encryption_key="password"`` on
|
|
421
|
+
``dump``/``dumps``/``dumpb``/``load``/``loads``/``Encoder``/``Decoder``
|
|
422
|
+
writes and reads standard `age <https://age-encryption.org>`_ v1 files
|
|
423
|
+
(scrypt passphrase, ChaCha20-Poly1305), decryptable by any age tool; any
|
|
424
|
+
modified byte or wrong password raises ``DecryptionError``; ``dumps``
|
|
425
|
+
returns the ASCII armored form, ``encryption_in_base64=True`` forces it
|
|
426
|
+
everywhere (bytes, files) and ``False`` forces the binary form; no extra
|
|
427
|
+
package: libsodium 1.0.22 is linked into the C extension (built from the
|
|
428
|
+
pinned ``libsodium/`` clone), payload segments spread over all cores
|
|
429
|
+
* WebAssembly wheel for Pyodide (``scripts/construit_wasm.sh``): runs in the
|
|
430
|
+
browser, encryption included, through the same linked libsodium
|
|
431
|
+
* position index: ``load(file, path="root['a'][0].b")`` reads one object of a
|
|
432
|
+
json file without parsing the rest, ``serializejson.index()`` indexes a file
|
|
433
|
+
already written and ``serializejson.paths()`` lists what it holds
|
|
434
|
+
* ``dump`` to a named file now writes that index by default, zstd compressed
|
|
435
|
+
in a hidden sidecar file of the same name preceded by a dot, which leaves
|
|
436
|
+
the json itself standard (``index="comment"`` appends it to the json as a
|
|
437
|
+
comment line instead — one single file to move, but no other parser reads it
|
|
438
|
+
any more; ``index=None`` writes none); files whose containers all stay under
|
|
439
|
+
``index_threshold`` keep no index at all
|
|
440
|
+
* Python 3.11 to 3.14 support (default ``object.__getstate__`` handled), numpy 2 support
|
|
441
|
+
* circular references and duplicates now handled for lists and dicts too (``$ref``),
|
|
442
|
+
including physically shared ``__dict__`` (restored at load, beyond pickle)
|
|
443
|
+
* big speedups: per-class fast paths fully in C++ (encode and decode),
|
|
444
|
+
SIMD parser, base64 written/read without intermediate strings,
|
|
445
|
+
readable numpy arrays written straight from their buffer (``ArrayRows``)
|
|
446
|
+
* blosc2 compression in C without Python round trip; DETERMINISTIC internal
|
|
447
|
+
multithreading via the bundled patched libblosc2 (same bytes whatever the
|
|
448
|
+
thread count); parallel base64; chunked parallel fallback (``b64_blosc2p``)
|
|
449
|
+
* default compression switched to ``blosc2_zstd`` (old ``b64_blosc`` files
|
|
450
|
+
still readable; new files need a blosc2-capable serializejson)
|
|
451
|
+
* homogeneous number lists written on a single line everywhere (dict values,
|
|
452
|
+
nested lists), decided in C++
|
|
453
|
+
* fixes: segfault on 3.12/3.13 with deep/cyclic data, ``append()`` of objects,
|
|
454
|
+
float subclasses written via ``repr()`` (numpy 2), docstring SyntaxWarnings
|
|
455
|
+
* reading rebuilds objects as the parse goes (``rehydrate=True``, the new
|
|
456
|
+
default): each instance is built as soon as its envelope is read, and with
|
|
457
|
+
``obj=`` the live objects are adopted in place (identities kept, arguments
|
|
458
|
+
reconciled one by one) instead of a dict tree then a second pass;
|
|
459
|
+
``rehydrate=False`` restores the previous behaviour
|
|
460
|
+
* Qt: signal/slot connections serialized by introspection (PySide6), whole
|
|
461
|
+
widget trees with ``qt_tree=True``, QTimer/QAction state, PySide6 enums;
|
|
462
|
+
``qtpy6`` replaces ``qtpy`` (PySide6 by default); QImage rows with a stride
|
|
463
|
+
not multiple of 4 bytes are no longer shifted
|
|
464
|
+
* ``datetime.datetime`` written as RFC 9557 text (``isoformat()``, plus
|
|
465
|
+
``[Zone/Name]`` for ``ZoneInfo``, which was not serializable before); the
|
|
466
|
+
former reduce forms are still read
|
|
467
|
+
* ``etat_sans_defauts(obj, defaults, properties)``: C helper building the flat
|
|
468
|
+
state of an object without its default values, for ``__serializejson__``
|
|
469
|
+
hooks written by applications
|
|
470
|
+
* classes with ``__setstate__`` are decoded in C with a single
|
|
471
|
+
``__setstate__`` call (-30 % on such objects, -43 % on a deep document of
|
|
472
|
+
452 objects), as are classes whose name is shortened by the application
|
|
473
|
+
|
|
474
|
+
Version 0.3.4
|
|
475
|
+
-------------
|
|
476
|
+
:Date: 2023-06-11
|
|
477
|
+
|
|
478
|
+
* Restore ducumentation
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
Version 0.3.3
|
|
482
|
+
-------------
|
|
483
|
+
:Date: 2022-10-18
|
|
484
|
+
|
|
485
|
+
* Big speed improvement for bytes and numpy array serialization
|
|
486
|
+
|
|
487
|
+
Version 0.3.2
|
|
488
|
+
-------------
|
|
489
|
+
:Date: 2022-10-01
|
|
490
|
+
|
|
491
|
+
* API changed
|
|
492
|
+
* add better support for cicular reférences and duplicates with {"$ref": ...}
|
|
493
|
+
|
|
494
|
+
Version 0.2.0
|
|
495
|
+
-------------
|
|
496
|
+
:Date: 2021-02-18
|
|
497
|
+
|
|
498
|
+
* API changed
|
|
499
|
+
* can serialize dict with no-string keys
|
|
500
|
+
* add support for cicular reférences and duplicates with {"$ref": ...}
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
Version 0.1.0
|
|
504
|
+
-------------
|
|
505
|
+
:Date: 2020-11-28
|
|
506
|
+
|
|
507
|
+
* change description for pipy
|
|
508
|
+
* add license for pipy
|
|
509
|
+
* enable load of tuple, time.struct_time, Counter, OrderedDict and defaultdict
|
|
510
|
+
|
|
511
|
+
Version 0.0.4
|
|
512
|
+
-------------
|
|
513
|
+
:Date: 2020-11-24
|
|
514
|
+
|
|
515
|
+
* API changed
|
|
516
|
+
* add plugins support
|
|
517
|
+
* add bytes, bytearray and numpy.array compression with blosc zstd
|
|
518
|
+
* fix itertive append and decode (not fully tested).
|
|
519
|
+
* fix dump of numpy types without conversion to python types(not yet numpy.float64)
|