Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ helps, and credit will always be given.

You can contribute in many ways:

Good First Contributions
------------------------

If you are new to the project, these are useful places to start:

* Improve examples for real-world API responses, files, and command-line usage.
* Add small tests around conversion options such as wrappers, list handling, CDATA, and XPath output.
* Improve benchmark documentation or add a reproducible benchmark case.
* Polish CLI behavior, error messages, and help text.
* Review the roadmap in ``ROADMAP.md`` and open a focused issue before starting larger changes.

Types of Contributions
----------------------

Expand Down Expand Up @@ -99,7 +110,7 @@ Ready to contribute? Here's how to set up `json2xml` for local development.
Rust Extension Development
--------------------------

The ``json2xml-rs`` Rust extension provides ~29x faster performance. If you want to contribute to the Rust extension:
The ``json2xml-rs`` Rust extension provides ~57-129x faster performance in the current benchmark. If you want to contribute to the Rust extension:

**Prerequisites**

Expand Down
89 changes: 87 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,100 @@ json2xml
.. image:: https://codecov.io/gh/vinitkumar/json2xml/branch/master/graph/badge.svg?token=Yt2h55eTL2
:target: https://codecov.io/gh/vinitkumar/json2xml

json2xml is a Python library that allows you to convert JSON data into XML format. It's simple, efficient, and easy to use.
json2xml is a Python library and CLI for converting JSON data into XML. It is designed for teams that need predictable XML output, Python-first ergonomics, and a faster native path when conversion speed matters.

Documentation: https://json2xml.readthedocs.io.

The library was initially dependent on the `dict2xml` project, but it has now been integrated into json2xml itself. This has led to cleaner code, the addition of types and tests, and overall improved performance.

**Looking for a Go version?** Check out `json2xml-go <https://github.com/vinitkumar/json2xml-go>`_, a Go port of this library with identical features and a native CLI tool.

Why json2xml?
^^^^^^^^^^^^^

Use json2xml when you need:

* A Python library for turning dictionaries, strings, files, or API responses into XML
* A command-line tool for quick JSON-to-XML conversion from scripts and terminals
* Optional Rust acceleration with automatic fallback to the pure Python implementation
* XPath 3.1 compatible output when standards-friendly XML is required
* A small, focused project with tests, docs, benchmarks, and multiple native implementation experiments

Quick Start
^^^^^^^^^^^

Install the Python package:

.. code-block:: console

pip install json2xml

Use it from Python:

.. code-block:: python

from json2xml import json2xml
from json2xml.utils import readfromstring

data = readfromstring('{"name": "Ada", "language": "Python"}')
print(json2xml.Json2xml(data).to_xml())

Use it from the terminal:

.. code-block:: console

json2xml-py -s '{"name": "Ada", "language": "Python"}'

Install the accelerated path:

.. code-block:: console

pip install json2xml[fast]

Performance Snapshot
^^^^^^^^^^^^^^^^^^^^

The optional Rust extension is the fastest path for Python callers because it avoids process startup overhead and falls back to pure Python when a feature is not supported natively.

.. list-table::
:header-rows: 1
:widths: 30 20 20 15

* - Test Case
- Pure Python
- Rust Extension
- Speedup
* - **Small JSON** (47 bytes)
- 31.49µs
- 0.55µs
- **56.8x**
* - **Medium JSON** (3.2 KB)
- 1.69ms
- 16.15µs
- **105.0x**
* - **Large JSON** (32 KB)
- 17.97ms
- 168.21µs
- **106.8x**
* - **Very Large JSON** (323 KB)
- 183.33ms
- 1.42ms
- **129.0x**

See `BENCHMARKS.md <https://github.com/vinitkumar/json2xml/blob/master/BENCHMARKS.md>`_ for the full Python, Rust, Go, and Zig comparison.

Project Roadmap
^^^^^^^^^^^^^^^

The next phase of json2xml is focused on making the project easier to adopt, benchmark, and contribute to:

* Improve examples for common API, file, and CLI workflows
* Add clearer contribution paths for docs, CLI polish, and benchmark coverage
* Keep comparing Python, Rust, Go, and Zig implementations with reproducible benchmarks
* Continue hardening the Rust extension fallback behavior across platforms

See `ROADMAP.md <https://github.com/vinitkumar/json2xml/blob/master/ROADMAP.md>`_ for more detail.



Architecture Diagram
Expand Down Expand Up @@ -538,4 +624,3 @@ Help and Support to maintain this project
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- You can sponsor my work for this plugin here: https://github.com/sponsors/vinitkumar/

60 changes: 60 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# json2xml Roadmap

json2xml is a small, practical JSON-to-XML toolkit for Python users, CLI workflows, and performance experiments across native implementations.

This roadmap keeps the project direction visible for users and contributors.

## Current Focus

- Make the README and examples easier for new users to scan.
- Keep the Python API stable while improving typed, tested behavior.
- Maintain the Rust acceleration path as the fastest option for Python callers.
- Keep Python, Rust, Go, and Zig benchmark results reproducible.

## Near-Term Work

### Documentation and Examples

- Add examples for converting API responses, local files, stdin, and string payloads.
- Document the differences between pure Python, Rust extension, Go CLI, and Zig CLI usage.
- Add a short "choose the right implementation" guide.
- Expand troubleshooting docs for installation and native wheel fallback.

### CLI Experience

- Improve error messages for invalid JSON, missing input, and unsupported option combinations.
- Add more CLI examples for shell pipelines and output files.
- Confirm behavior is consistent across macOS, Linux, and Windows.

### Performance and Benchmarks

- Keep `BENCHMARKS.md` updated when benchmark scripts or implementation details change.
- Add benchmark notes that explain process startup overhead for CLI tools.
- Add larger input fixtures that reflect real integration workloads.
- Make it easy for contributors to reproduce benchmark runs locally.

### Rust Extension

- Continue improving fallback behavior when native support is unavailable.
- Add tests for unsupported or partially supported conversion features.
- Keep PyO3 and packaging configuration current.
- Verify wheels across supported Python and platform versions.

## Good First Issues

These are intentionally small and useful:

- Add one new README example for a real-world JSON shape.
- Add a regression test for a documented conversion option.
- Improve one CLI help message or error case.
- Add a short benchmark reproduction note.
- Clarify one section of `CONTRIBUTING.rst`.

## Larger Ideas

- Streaming support for very large JSON inputs.
- More explicit XML namespace handling examples.
- Better comparison docs against adjacent JSON-to-XML tools.
- A small gallery of before/after JSON and XML examples.

If you want to help, open an issue with a focused proposal or pick an existing issue labeled `good first issue`, `help wanted`, `docs`, `cli`, or `performance`.
4 changes: 2 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
class JsonTestHandler(BaseHTTPRequestHandler):
"""Tiny HTTP handler for exercising the real URL reader."""

responses: ClassVar[dict[str, tuple[int, bytes]]] = {
json_responses: ClassVar[dict[str, tuple[int, bytes]]] = {
"/data.json": (200, b'{"key": "value", "number": 42}'),
"/api": (200, b'{"result": "success"}'),
"/invalid.json": (200, b"invalid json content"),
Expand All @@ -41,7 +41,7 @@ class JsonTestHandler(BaseHTTPRequestHandler):

def do_GET(self) -> None:
path = self.path.split("?", 1)[0]
status, body = self.responses.get(path, (404, b'{"error": "not found"}'))
status, body = self.json_responses.get(path, (404, b'{"error": "not found"}'))
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
Expand Down
Loading