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.
Files changed (119) hide show
  1. serializejson-0.4.0/CHANGELOG.rst +104 -0
  2. serializejson-0.4.0/MANIFEST.in +16 -0
  3. serializejson-0.4.0/PKG-INFO +519 -0
  4. serializejson-0.4.0/README.rst +358 -0
  5. serializejson-0.4.0/pyproject.toml +24 -0
  6. serializejson-0.4.0/rapidjson/allocators.h +692 -0
  7. serializejson-0.4.0/rapidjson/blosc2_determinisme.patch +198 -0
  8. serializejson-0.4.0/rapidjson/blosc2_headers/blosc2/blosc2-common.h +80 -0
  9. serializejson-0.4.0/rapidjson/blosc2_headers/blosc2/blosc2-export.h +48 -0
  10. serializejson-0.4.0/rapidjson/blosc2_headers/blosc2/blosc2-stdio.h +141 -0
  11. serializejson-0.4.0/rapidjson/blosc2_headers/blosc2.h +2911 -0
  12. serializejson-0.4.0/rapidjson/cursorstreamwrapper.h +78 -0
  13. serializejson-0.4.0/rapidjson/document.h +3043 -0
  14. serializejson-0.4.0/rapidjson/dtoa_repr.h +273 -0
  15. serializejson-0.4.0/rapidjson/eisel_lemire.h +120 -0
  16. serializejson-0.4.0/rapidjson/eisel_lemire_table.h +665 -0
  17. serializejson-0.4.0/rapidjson/encodedstream.h +299 -0
  18. serializejson-0.4.0/rapidjson/encodings.h +716 -0
  19. serializejson-0.4.0/rapidjson/error/en.h +122 -0
  20. serializejson-0.4.0/rapidjson/error/error.h +216 -0
  21. serializejson-0.4.0/rapidjson/fdwritestream.h +353 -0
  22. serializejson-0.4.0/rapidjson/filereadstream.h +99 -0
  23. serializejson-0.4.0/rapidjson/filewritestream.h +104 -0
  24. serializejson-0.4.0/rapidjson/fwd.h +151 -0
  25. serializejson-0.4.0/rapidjson/indexscan.h +993 -0
  26. serializejson-0.4.0/rapidjson/internal/biginteger.h +297 -0
  27. serializejson-0.4.0/rapidjson/internal/clzll.h +71 -0
  28. serializejson-0.4.0/rapidjson/internal/diyfp.h +261 -0
  29. serializejson-0.4.0/rapidjson/internal/dtoa.h +249 -0
  30. serializejson-0.4.0/rapidjson/internal/ieee754.h +78 -0
  31. serializejson-0.4.0/rapidjson/internal/itoa.h +308 -0
  32. serializejson-0.4.0/rapidjson/internal/meta.h +186 -0
  33. serializejson-0.4.0/rapidjson/internal/pow10.h +55 -0
  34. serializejson-0.4.0/rapidjson/internal/regex.h +739 -0
  35. serializejson-0.4.0/rapidjson/internal/stack.h +232 -0
  36. serializejson-0.4.0/rapidjson/internal/strfunc.h +83 -0
  37. serializejson-0.4.0/rapidjson/internal/strtod.h +318 -0
  38. serializejson-0.4.0/rapidjson/internal/swap.h +46 -0
  39. serializejson-0.4.0/rapidjson/istreamwrapper.h +128 -0
  40. serializejson-0.4.0/rapidjson/libsodium_statique.py +48 -0
  41. serializejson-0.4.0/rapidjson/memorybuffer.h +72 -0
  42. serializejson-0.4.0/rapidjson/memorystream.h +71 -0
  43. serializejson-0.4.0/rapidjson/msinttypes/inttypes.h +316 -0
  44. serializejson-0.4.0/rapidjson/msinttypes/stdint.h +300 -0
  45. serializejson-0.4.0/rapidjson/ostreamwrapper.h +81 -0
  46. serializejson-0.4.0/rapidjson/pgo_workload.py +159 -0
  47. serializejson-0.4.0/rapidjson/pointer.h +1482 -0
  48. serializejson-0.4.0/rapidjson/prettywriter.h +521 -0
  49. serializejson-0.4.0/rapidjson/pybytesbuffer.h +284 -0
  50. serializejson-0.4.0/rapidjson/pywritestreamwrapper.h +214 -0
  51. serializejson-0.4.0/rapidjson/rapidjson.cpp +12641 -0
  52. serializejson-0.4.0/rapidjson/rapidjson.h +741 -0
  53. serializejson-0.4.0/rapidjson/reader.h +3037 -0
  54. serializejson-0.4.0/rapidjson/ryu_d2d_table.h +635 -0
  55. serializejson-0.4.0/rapidjson/schema.h +2816 -0
  56. serializejson-0.4.0/rapidjson/serializejson.h +2332 -0
  57. serializejson-0.4.0/rapidjson/sjcrypto.h +246 -0
  58. serializejson-0.4.0/rapidjson/stream.h +223 -0
  59. serializejson-0.4.0/rapidjson/stringbuffer.h +126 -0
  60. serializejson-0.4.0/rapidjson/uri.h +481 -0
  61. serializejson-0.4.0/rapidjson/version.txt +1 -0
  62. serializejson-0.4.0/rapidjson/writer.h +802 -0
  63. serializejson-0.4.0/rapidjson/writerthread.h +967 -0
  64. serializejson-0.4.0/scripts/construit_libblosc2_serializejson.sh +27 -0
  65. serializejson-0.4.0/serializejson/__init__.py +4647 -0
  66. serializejson-0.4.0/serializejson/_encryption.py +362 -0
  67. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/image/image_conversion.py +54 -15
  68. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/serialize/__init__.py +1 -1
  69. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/objects.py +7 -2
  70. serializejson-0.4.0/serializejson/indexation.py +424 -0
  71. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/pickle_PyQt5_PySide2.py +30 -21
  72. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/serializejson_PyQt5_PySide2.py +450 -251
  73. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/serializejson_array.py +2 -6
  74. serializejson-0.4.0/serializejson/plugins/serializejson_builtins.py +229 -0
  75. serializejson-0.4.0/serializejson/plugins/serializejson_datetime.py +66 -0
  76. serializejson-0.4.0/serializejson/plugins/serializejson_numpy.py +438 -0
  77. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/tools.py +293 -28
  78. serializejson-0.4.0/serializejson.egg-info/PKG-INFO +519 -0
  79. serializejson-0.4.0/serializejson.egg-info/SOURCES.txt +102 -0
  80. serializejson-0.4.0/serializejson.egg-info/requires.txt +11 -0
  81. serializejson-0.4.0/serializejson.egg-info/top_level.txt +1 -0
  82. serializejson-0.4.0/setup.py +167 -0
  83. serializejson-0.3.3/CHANGELOG.rst +0 -39
  84. serializejson-0.3.3/PKG-INFO +0 -238
  85. serializejson-0.3.3/README.rst +0 -164
  86. serializejson-0.3.3/pyproject.toml +0 -9
  87. serializejson-0.3.3/rapidjson/rapidjson.cpp +0 -3765
  88. serializejson-0.3.3/serializejson/__init__.py +0 -2339
  89. serializejson-0.3.3/serializejson/plugins/serializejson_builtins.py +0 -141
  90. serializejson-0.3.3/serializejson/plugins/serializejson_datetime.py +0 -36
  91. serializejson-0.3.3/serializejson/plugins/serializejson_numpy.py +0 -254
  92. serializejson-0.3.3/serializejson.egg-info/PKG-INFO +0 -238
  93. serializejson-0.3.3/serializejson.egg-info/SOURCES.txt +0 -43
  94. serializejson-0.3.3/serializejson.egg-info/requires.txt +0 -16
  95. serializejson-0.3.3/serializejson.egg-info/top_level.txt +0 -3
  96. serializejson-0.3.3/setup.py +0 -107
  97. serializejson-0.3.3/tests/test_iterator.py +0 -21
  98. serializejson-0.3.3/tests/test_serialize_vs_pickle.py +0 -600
  99. {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE-APACHE.rst +0 -0
  100. {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE-PATRON.rst +0 -0
  101. {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE-PROSPERITY.rst +0 -0
  102. {serializejson-0.3.3 → serializejson-0.4.0}/LICENSE.rst +0 -0
  103. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/__init__.py +0 -0
  104. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/files/__init__.py +0 -0
  105. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/image/__init__.py +0 -0
  106. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/string/__init__.py +0 -0
  107. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/string/encodings/__init__.py +0 -0
  108. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/string/encodings/ascii_printables.py +0 -0
  109. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/__init__.py +0 -0
  110. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/dictionaries.py +0 -0
  111. {serializejson-0.3.3/SmartFramework → serializejson-0.4.0/serializejson/_smartframework}/tools/functions.py +0 -0
  112. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/__init__.py +0 -0
  113. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/plugins/module_name.py +0 -0
  114. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/serialize_parameters.py +0 -0
  115. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/simple_exemple.py +0 -0
  116. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson/simple_exemple_update.py +0 -0
  117. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson.egg-info/dependency_links.txt +0 -0
  118. {serializejson-0.3.3 → serializejson-0.4.0}/serializejson.egg-info/not-zip-safe +0 -0
  119. {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)