json2xml 6.5.0__tar.gz → 7.0.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.
- {json2xml-6.5.0 → json2xml-7.0.0}/CONTRIBUTING.rst +8 -12
- {json2xml-6.5.0 → json2xml-7.0.0}/HISTORY.rst +32 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/MANIFEST.in +1 -1
- {json2xml-6.5.0 → json2xml-7.0.0}/PKG-INFO +33 -22
- {json2xml-6.5.0 → json2xml-7.0.0}/README.rst +25 -16
- json2xml-7.0.0/docs/benchmarks.rst +480 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/conf.py +23 -32
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/installation.rst +1 -2
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/rust_memory_benchmark.rst +2 -2
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/usage.rst +21 -2
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml/__init__.py +1 -1
- json2xml-7.0.0/json2xml/backend_selector.py +127 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml/cli.py +12 -9
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml/dicttoxml.py +365 -244
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml/dicttoxml_fast.py +60 -7
- json2xml-7.0.0/json2xml/json2xml.py +121 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml/types.py +4 -1
- json2xml-7.0.0/json2xml/utils.py +356 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml.egg-info/PKG-INFO +33 -22
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml.egg-info/SOURCES.txt +2 -2
- json2xml-7.0.0/json2xml.egg-info/requires.txt +15 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/pyproject.toml +20 -8
- json2xml-7.0.0/setup.cfg +4 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/setup.py +0 -1
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/conftest.py +8 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_backend_selector.py +6 -1
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_benchmark_multi_python.py +24 -3
- json2xml-7.0.0/tests/test_benchmark_security_hardening.py +84 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_cli.py +117 -51
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_dict2xml.py +267 -106
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_dicttoxml_fast_fallback.py +72 -2
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_dicttoxml_unit.py +223 -53
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_json2xml.py +235 -91
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_missing_coverage.py +9 -2
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/test_rust_dicttoxml.py +98 -33
- json2xml-7.0.0/tests/test_rust_python_parity.py +262 -0
- json2xml-7.0.0/tests/test_utils.py +790 -0
- json2xml-6.5.0/docs/benchmarks.rst +0 -203
- json2xml-6.5.0/json2xml/backend_selector.py +0 -63
- json2xml-6.5.0/json2xml/json2xml.py +0 -65
- json2xml-6.5.0/json2xml/utils.py +0 -87
- json2xml-6.5.0/json2xml.egg-info/requires.txt +0 -13
- json2xml-6.5.0/requirements.in +0 -3
- json2xml-6.5.0/setup.cfg +0 -11
- json2xml-6.5.0/tests/test_utils.py +0 -291
- {json2xml-6.5.0 → json2xml-7.0.0}/AUTHORS.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/LICENSE +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/Makefile +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/authors.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/contributing.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/history.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/index.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/json2xml.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/make.bat +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/modules.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/docs/readme.rst +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml.egg-info/dependency_links.txt +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml.egg-info/entry_points.txt +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/json2xml.egg-info/top_level.txt +0 -0
- {json2xml-6.5.0 → json2xml-7.0.0}/tests/__init__.py +0 -0
|
@@ -80,8 +80,7 @@ Ready to contribute? Here's how to set up `json2xml` for local development.
|
|
|
80
80
|
$ cd json2xml/
|
|
81
81
|
$ uv venv
|
|
82
82
|
$ source .venv/bin/activate
|
|
83
|
-
$ uv pip install -
|
|
84
|
-
$ uv pip install -e .
|
|
83
|
+
$ uv pip install -e ".[dev]"
|
|
85
84
|
|
|
86
85
|
4. Create a branch for local development::
|
|
87
86
|
|
|
@@ -96,7 +95,7 @@ Ready to contribute? Here's how to set up `json2xml` for local development.
|
|
|
96
95
|
|
|
97
96
|
# Or individually:
|
|
98
97
|
$ ruff check json2xml tests
|
|
99
|
-
$
|
|
98
|
+
$ uvx ty check json2xml tests
|
|
100
99
|
$ pytest tests/
|
|
101
100
|
|
|
102
101
|
6. Commit your changes and push your branch to GitHub::
|
|
@@ -140,7 +139,7 @@ Install Rust and maturin::
|
|
|
140
139
|
|
|
141
140
|
::
|
|
142
141
|
|
|
143
|
-
$ python benchmark_rust.py
|
|
142
|
+
$ python benchmarks/benchmark_rust.py
|
|
144
143
|
|
|
145
144
|
**Rust Code Structure**
|
|
146
145
|
|
|
@@ -182,12 +181,9 @@ To run a subset of tests::
|
|
|
182
181
|
Deploying
|
|
183
182
|
---------
|
|
184
183
|
|
|
185
|
-
A reminder for
|
|
186
|
-
Make sure all your changes are committed (including an entry in HISTORY.rst).
|
|
187
|
-
Then run::
|
|
188
|
-
|
|
189
|
-
Update the version in pyproject.toml and json2xml/__init__.py
|
|
190
|
-
$ git push
|
|
191
|
-
$ git push --tags
|
|
184
|
+
A reminder for maintainers on how to deploy:
|
|
192
185
|
|
|
193
|
-
|
|
186
|
+
#. Update the version in ``pyproject.toml`` and ``json2xml/__init__.py``.
|
|
187
|
+
#. Add the release notes to ``HISTORY.rst``.
|
|
188
|
+
#. Run ``make test-all`` and ``make dist``.
|
|
189
|
+
#. Publish the verified artifacts with ``uv publish dist/*``.
|
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
|
|
2
|
+
7.0.0 / 2026-08-23
|
|
3
|
+
==================
|
|
4
|
+
|
|
5
|
+
* breaking: make compact UTF-8 ``bytes`` the default public and CLI output; callers that require pretty Unicode text must pass ``pretty=True`` or ``--pretty``
|
|
6
|
+
* fix: normalize the parent name a ``list_headers`` dict member borrows, so a rootless list of dictionaries no longer emits the malformed empty tag ``<>``
|
|
7
|
+
* fix: make the optional Rust backend byte-identical to the Python serializer for every payload it accepts, correcting CDATA on numbers, nested list shapes, list member tag names, ``type="dict"`` under ``list_headers``, and names beginning with ``xml``
|
|
8
|
+
* fix: keep payloads the Rust backend cannot reproduce exactly -- non-JSON-native values, parser-resolved key names, and normalized root names -- on the Python serializer
|
|
9
|
+
* perf: run the Rust backend's payload gate natively, cutting a 1,000-record conversion from 1.51 ms to 0.49 ms
|
|
10
|
+
* fix: enforce conversion output limits from generated UTF-8 bytes instead of rejecting valid payloads with a conservative estimate
|
|
11
|
+
* fix: reject unsupported falsy objects consistently instead of serializing them as null
|
|
12
|
+
* fix: keep public scalar converter attribute dictionaries unchanged
|
|
13
|
+
* perf: validate common ASCII XML attribute names without constructing a DOM
|
|
14
|
+
* fix: serialize date-like values consistently at the root, which previously rejected ``datetime.time`` while accepting it inside dicts and lists
|
|
15
|
+
* refactor: dispatch every element writer through a single type classifier
|
|
16
|
+
* docs: record the string-returning public converters as a retained compatibility surface
|
|
17
|
+
* perf: indent pretty output while serializing instead of re-tokenizing generated XML, roughly halving pretty conversion time and removing the last XML parsing path from the library
|
|
18
|
+
* chore: release ``json2xml-rs`` 0.5.0 first and require it from ``json2xml[fast]`` for parity-safe accelerated installs
|
|
19
|
+
* chore: align local pytest, pre-commit, release, and Rust CI configuration with the supported toolchain
|
|
20
|
+
* chore: move benchmark scripts under ``benchmarks/`` and make ``pyproject.toml`` plus ``uv.lock`` the only dependency declaration
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
6.5.1 / 2026-08-05
|
|
24
|
+
==================
|
|
25
|
+
|
|
26
|
+
* security: pin URL connections to validated DNS addresses to prevent DNS-rebinding bypasses of private-network blocking
|
|
27
|
+
* security: bound encoded and decoded compressed responses to prevent gzip and deflate resource-exhaustion attacks
|
|
28
|
+
* fix: reject XML 1.0-forbidden characters consistently across Python and Rust serializers instead of emitting invalid XML
|
|
29
|
+
* fix: require an actual boolean for ``allow_private_networks`` and normalize malformed-hostname failures as ``URLReadError``
|
|
30
|
+
* chore: release ``json2xml-rs`` 0.4.3 first and require it from ``json2xml[fast]`` for XML-safe accelerated installs
|
|
31
|
+
* docs: document URL safety controls, XML validation behavior, migration guidance, and the Rust-first release sequence
|
|
32
|
+
|
|
33
|
+
|
|
2
34
|
6.5.0 / 2026-07-15
|
|
3
35
|
==================
|
|
4
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: json2xml
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.0
|
|
4
4
|
Summary: Simple Python Library to convert JSON to XML
|
|
5
5
|
Author-email: Vinit Kumar <mail@vinitkumar.me>
|
|
6
6
|
License: Apache Software License 2.0
|
|
@@ -26,13 +26,15 @@ Requires-Dist: defusedxml
|
|
|
26
26
|
Requires-Dist: urllib3>=2.7.0
|
|
27
27
|
Provides-Extra: dev
|
|
28
28
|
Requires-Dist: pytest>=8.4.1; extra == "dev"
|
|
29
|
-
Requires-Dist: pytest-cov; extra == "dev"
|
|
30
|
-
Requires-Dist:
|
|
31
|
-
Requires-Dist:
|
|
29
|
+
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-xdist>=3.8.0; extra == "dev"
|
|
31
|
+
Requires-Dist: coverage>=7.15.4; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff>=0.16.3; extra == "dev"
|
|
33
|
+
Requires-Dist: setuptools>=80.9.0; extra == "dev"
|
|
32
34
|
Requires-Dist: pygments>=2.20.0; extra == "dev"
|
|
33
|
-
Requires-Dist: xmltodict>=0.
|
|
35
|
+
Requires-Dist: xmltodict>=0.14.2; extra == "dev"
|
|
34
36
|
Provides-Extra: fast
|
|
35
|
-
Requires-Dist: json2xml-rs>=0.
|
|
37
|
+
Requires-Dist: json2xml-rs>=0.5.0; extra == "fast"
|
|
36
38
|
Dynamic: license-file
|
|
37
39
|
|
|
38
40
|
.. image:: ./json2xml-hero.png
|
|
@@ -276,11 +278,30 @@ You can use the json2xml library in the following ways:
|
|
|
276
278
|
data = readfromjson("examples/licht.json")
|
|
277
279
|
print(json2xml.Json2xml(data).to_xml())
|
|
278
280
|
|
|
281
|
+
URL reads accept only credential-free HTTP(S), reject redirects and non-public
|
|
282
|
+
destinations by default, pin public connections to their validated DNS address,
|
|
283
|
+
and stop after 10 MiB of encoded or decoded content. Gzip and deflate responses
|
|
284
|
+
honor ``Content-Length`` and are decoded incrementally; other content encodings
|
|
285
|
+
are rejected. Trusted library callers can opt into a private endpoint with the
|
|
286
|
+
boolean ``True`` or choose a smaller limit:
|
|
287
|
+
|
|
288
|
+
.. code-block:: python
|
|
289
|
+
|
|
290
|
+
data = readfromurl(
|
|
291
|
+
"http://127.0.0.1:8000/data.json",
|
|
292
|
+
allow_private_networks=True,
|
|
293
|
+
max_response_bytes=1024 * 1024,
|
|
294
|
+
)
|
|
295
|
+
|
|
279
296
|
|
|
280
297
|
Custom Wrappers and Indentation
|
|
281
298
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
282
299
|
|
|
283
|
-
By default, a wrapper `all` and pretty
|
|
300
|
+
By default, a wrapper `all` and compact output (``pretty=False``) are set. Pretty printing can be enabled explicitly:
|
|
301
|
+
|
|
302
|
+
Conversions also default to a nesting limit of 100, an item limit of 100,000,
|
|
303
|
+
and a 10 MiB XML output limit. Pass ``max_depth``, ``max_items``, or
|
|
304
|
+
``max_output_bytes`` to choose smaller budgets for untrusted workloads.
|
|
284
305
|
|
|
285
306
|
.. code-block:: python
|
|
286
307
|
|
|
@@ -434,8 +455,7 @@ This project uses modern Python development practices. Here's how to set up a de
|
|
|
434
455
|
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
435
456
|
|
|
436
457
|
# Install dependencies
|
|
437
|
-
uv pip install -
|
|
438
|
-
uv pip install -e .
|
|
458
|
+
uv pip install -e ".[dev]"
|
|
439
459
|
|
|
440
460
|
**Running Tests and Checks**
|
|
441
461
|
|
|
@@ -447,25 +467,16 @@ Using Make (recommended):
|
|
|
447
467
|
|
|
448
468
|
make test # Run tests with coverage
|
|
449
469
|
make lint # Run linting with ruff
|
|
450
|
-
make typecheck # Run type checking with
|
|
470
|
+
make typecheck # Run type checking with ty
|
|
451
471
|
make check-all # Run all checks (lint, typecheck, test)
|
|
452
472
|
|
|
453
|
-
Using the development script:
|
|
454
|
-
|
|
455
|
-
.. code-block:: console
|
|
456
|
-
|
|
457
|
-
python dev.py # Run all checks
|
|
458
|
-
python dev.py test # Run tests only
|
|
459
|
-
python dev.py lint # Run linting only
|
|
460
|
-
python dev.py typecheck # Run type checking only
|
|
461
|
-
|
|
462
473
|
Using tools directly:
|
|
463
474
|
|
|
464
475
|
.. code-block:: console
|
|
465
476
|
|
|
466
477
|
pytest --cov=json2xml --cov-report=term -xvs tests -n auto
|
|
467
478
|
ruff check json2xml tests
|
|
468
|
-
|
|
479
|
+
uvx ty check json2xml tests
|
|
469
480
|
|
|
470
481
|
**Rust Extension Development**
|
|
471
482
|
|
|
@@ -500,7 +511,7 @@ Running Rust benchmarks:
|
|
|
500
511
|
.. code-block:: console
|
|
501
512
|
|
|
502
513
|
# After building the extension
|
|
503
|
-
python benchmark_rust.py
|
|
514
|
+
python benchmarks/benchmark_rust.py
|
|
504
515
|
|
|
505
516
|
The Rust code is in ``rust/src/lib.rs`` and uses PyO3 for Python bindings.
|
|
506
517
|
|
|
@@ -550,7 +561,7 @@ The ``json2xml-py`` command-line tool provides an easy way to convert JSON to XM
|
|
|
550
561
|
Conversion Options:
|
|
551
562
|
-w, --wrapper string Wrapper element name (default "all")
|
|
552
563
|
-r, --root Include root element (default true)
|
|
553
|
-
-p, --pretty Pretty print output (default
|
|
564
|
+
-p, --pretty Pretty print output (default false)
|
|
554
565
|
-t, --type Include type attributes (default true)
|
|
555
566
|
-i, --item-wrap Wrap list items in <item> elements (default true)
|
|
556
567
|
-x, --xpath Use XPath 3.1 json-to-xml format
|
|
@@ -239,11 +239,30 @@ You can use the json2xml library in the following ways:
|
|
|
239
239
|
data = readfromjson("examples/licht.json")
|
|
240
240
|
print(json2xml.Json2xml(data).to_xml())
|
|
241
241
|
|
|
242
|
+
URL reads accept only credential-free HTTP(S), reject redirects and non-public
|
|
243
|
+
destinations by default, pin public connections to their validated DNS address,
|
|
244
|
+
and stop after 10 MiB of encoded or decoded content. Gzip and deflate responses
|
|
245
|
+
honor ``Content-Length`` and are decoded incrementally; other content encodings
|
|
246
|
+
are rejected. Trusted library callers can opt into a private endpoint with the
|
|
247
|
+
boolean ``True`` or choose a smaller limit:
|
|
248
|
+
|
|
249
|
+
.. code-block:: python
|
|
250
|
+
|
|
251
|
+
data = readfromurl(
|
|
252
|
+
"http://127.0.0.1:8000/data.json",
|
|
253
|
+
allow_private_networks=True,
|
|
254
|
+
max_response_bytes=1024 * 1024,
|
|
255
|
+
)
|
|
256
|
+
|
|
242
257
|
|
|
243
258
|
Custom Wrappers and Indentation
|
|
244
259
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
245
260
|
|
|
246
|
-
By default, a wrapper `all` and pretty
|
|
261
|
+
By default, a wrapper `all` and compact output (``pretty=False``) are set. Pretty printing can be enabled explicitly:
|
|
262
|
+
|
|
263
|
+
Conversions also default to a nesting limit of 100, an item limit of 100,000,
|
|
264
|
+
and a 10 MiB XML output limit. Pass ``max_depth``, ``max_items``, or
|
|
265
|
+
``max_output_bytes`` to choose smaller budgets for untrusted workloads.
|
|
247
266
|
|
|
248
267
|
.. code-block:: python
|
|
249
268
|
|
|
@@ -397,8 +416,7 @@ This project uses modern Python development practices. Here's how to set up a de
|
|
|
397
416
|
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
398
417
|
|
|
399
418
|
# Install dependencies
|
|
400
|
-
uv pip install -
|
|
401
|
-
uv pip install -e .
|
|
419
|
+
uv pip install -e ".[dev]"
|
|
402
420
|
|
|
403
421
|
**Running Tests and Checks**
|
|
404
422
|
|
|
@@ -410,25 +428,16 @@ Using Make (recommended):
|
|
|
410
428
|
|
|
411
429
|
make test # Run tests with coverage
|
|
412
430
|
make lint # Run linting with ruff
|
|
413
|
-
make typecheck # Run type checking with
|
|
431
|
+
make typecheck # Run type checking with ty
|
|
414
432
|
make check-all # Run all checks (lint, typecheck, test)
|
|
415
433
|
|
|
416
|
-
Using the development script:
|
|
417
|
-
|
|
418
|
-
.. code-block:: console
|
|
419
|
-
|
|
420
|
-
python dev.py # Run all checks
|
|
421
|
-
python dev.py test # Run tests only
|
|
422
|
-
python dev.py lint # Run linting only
|
|
423
|
-
python dev.py typecheck # Run type checking only
|
|
424
|
-
|
|
425
434
|
Using tools directly:
|
|
426
435
|
|
|
427
436
|
.. code-block:: console
|
|
428
437
|
|
|
429
438
|
pytest --cov=json2xml --cov-report=term -xvs tests -n auto
|
|
430
439
|
ruff check json2xml tests
|
|
431
|
-
|
|
440
|
+
uvx ty check json2xml tests
|
|
432
441
|
|
|
433
442
|
**Rust Extension Development**
|
|
434
443
|
|
|
@@ -463,7 +472,7 @@ Running Rust benchmarks:
|
|
|
463
472
|
.. code-block:: console
|
|
464
473
|
|
|
465
474
|
# After building the extension
|
|
466
|
-
python benchmark_rust.py
|
|
475
|
+
python benchmarks/benchmark_rust.py
|
|
467
476
|
|
|
468
477
|
The Rust code is in ``rust/src/lib.rs`` and uses PyO3 for Python bindings.
|
|
469
478
|
|
|
@@ -513,7 +522,7 @@ The ``json2xml-py`` command-line tool provides an easy way to convert JSON to XM
|
|
|
513
522
|
Conversion Options:
|
|
514
523
|
-w, --wrapper string Wrapper element name (default "all")
|
|
515
524
|
-r, --root Include root element (default true)
|
|
516
|
-
-p, --pretty Pretty print output (default
|
|
525
|
+
-p, --pretty Pretty print output (default false)
|
|
517
526
|
-t, --type Include type attributes (default true)
|
|
518
527
|
-i, --item-wrap Wrap list items in <item> elements (default true)
|
|
519
528
|
-x, --xpath Use XPath 3.1 json-to-xml format
|