Skip to main content

Simple Python Library to convert JSON to XML

Project description

json2xml hero

json2xml

https://badge.fury.io/py/json2xml.svg https://static.pepy.tech/personalized-badge/json2xml?period=total&units=international_system&left_color=blue&right_color=orange&left_text=Downloads https://github.com/vinitkumar/json2xml/actions/workflows/pythonpackage.yml/badge.svg https://img.shields.io/pypi/pyversions/json2xml.svg Documentation Status https://codecov.io/gh/vinitkumar/json2xml/branch/master/graph/badge.svg?token=Yt2h55eTL2

json2xml is a Python library that allows you to convert JSON data into XML format. It’s simple, efficient, and easy to use.

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, a Go port of this library with identical features and a native CLI tool.

Architecture Diagram

./diagram.png

Installation

As a Library

pip install json2xml

With Native Rust Acceleration (28x faster)

For maximum performance, install the optional Rust extension:

# Install json2xml with Rust acceleration
pip install json2xml[fast]

# Or install the Rust extension separately
pip install json2xml-rs

The Rust extension provides 28x faster conversion compared to pure Python. It’s automatically used when available, with seamless fallback to pure Python.

As a CLI Tool

The library includes a command-line tool json2xml-py that gets installed automatically:

pip install json2xml

# Now you can use it from the command line
json2xml-py data.json
json2xml-py -s '{"name": "John", "age": 30}'
json2xml-py -u https://api.example.com/data.json

For CLI options, run json2xml-py --help.

Features

json2xml supports the following features:

  • Conversion from a json string to XML

  • Conversion from a json file to XML

  • Conversion from an API that emits json data to XML

  • Compliant with the json-to-xml function specification from XPath 3.1

  • Command-line tool for easy conversion from the terminal

Usage

You can use the json2xml library in the following ways:

from json2xml import json2xml
from json2xml.utils import readfromurl, readfromstring, readfromjson

# Convert JSON data from a URL to XML
data = readfromurl("https://api.publicapis.org/entries")
print(json2xml.Json2xml(data).to_xml())

# Convert a JSON string to XML
data = readfromstring(
    '{"login":"mojombo","id":1,"avatar_url":"https://avatars0.githubusercontent.com/u/1?v=4"}'
)
print(json2xml.Json2xml(data).to_xml())

# Convert a JSON file to XML
data = readfromjson("examples/licht.json")
print(json2xml.Json2xml(data).to_xml())

Custom Wrappers and Indentation

By default, a wrapper all and pretty True is set. However, you can easily change this in your code like this:

from json2xml import json2xml
from json2xml.utils import readfromurl, readfromstring, readfromjson

data = readfromstring(
    '{"login":"mojombo","id":1,"avatar_url":"https://avatars0.githubusercontent.com/u/1?v=4"}'
)
print(json2xml.Json2xml(data, wrapper="all", pretty=True).to_xml())

Outputs this:

<?xml version="1.0" encoding="UTF-8"?>
<all>
  <login type="str">mojombo</login>
  <id type="int">1</id>
  <avatar_url type="str">https://avatars0.githubusercontent.com/u/1?v=4</avatar_url>
</all>

Omit List item

Assume the following json input

{
  "my_items": [
    { "my_item": { "id": 1 } },
    { "my_item": { "id": 2 } }
  ],
  "my_str_items": ["a", "b"]
}

By default, items in an array are wrapped in <item></item>.

Default output:

<?xml version="1.0" ?>
<all>
  <my_items type="list">
    <item type="dict">
      <my_item type="dict">
        <id type="int">1</id>
      </my_item>
    </item>
    <item type="dict">
      <my_item type="dict">
        <id type="int">2</id>
      </my_item>
    </item>
  </my_items>
  <my_str_items type="list">
    <item type="str">a</item>
    <item type="str">b</item>
  </my_str_items>
  <empty type="list"/>
</all>

However, you can change this behavior using the item_wrap property like this:

from json2xml import json2xml
from json2xml.utils import readfromurl, readfromstring, readfromjson

data = readfromstring('{"my_items":[{"my_item":{"id":1} },{"my_item":{"id":2} }],"my_str_items":["a","b"]}')
print(json2xml.Json2xml(data, item_wrap=False).to_xml())

Outputs this:

<?xml version="1.0" ?>
<all>
  <my_items type="list">
    <my_item type="dict">
      <id type="int">1</id>
    </my_item>
    <my_item type="dict">
      <id type="int">2</id>
    </my_item>
  </my_items>
  <my_str_items type="str">a</my_str_items>
  <my_str_items type="str">b</my_str_items>
</all>

Optional Attribute Type Support

You can also specify if the output XML needs to have type specified or not. Here is the usage:

from json2xml import json2xml
from json2xml.utils import readfromurl, readfromstring, readfromjson

data = readfromstring(
    '{"login":"mojombo","id":1,"avatar_url":"https://avatars0.githubusercontent.com/u/1?v=4"}'
)
print(json2xml.Json2xml(data, wrapper="all", pretty=True, attr_type=False).to_xml())

Outputs this:

<?xml version="1.0" ?>
<all>
  <login>mojombo</login>
  <id>1</id>
  <avatar_url>https://avatars0.githubusercontent.com/u/1?v=4</avatar_url>
</all>

XPath 3.1 Compliance Options

The library supports the optional xpath_format parameter which makes the output compliant with the json-to-xml function specification from XPath 3.1. When enabled, the XML output follows the standardized format defined by the W3C specification.

from json2xml import json2xml
from json2xml.utils import readfromstring

data = readfromstring(
    '{"login":"mojombo","id":1,"avatar_url":"https://avatars0.githubusercontent.com/u/1?v=4"}'
)
# Use xpath_format=True for XPath 3.1 compliant output
print(json2xml.Json2xml(data, xpath_format=True).to_xml())

The methods are simple and easy to use and there are also checks inside of code to exit cleanly in case any of the input(file, string or API URL) returns invalid JSON.

Development

This project uses modern Python development practices. Here’s how to set up a development environment:

# Create and activate virtual environment (using uv - recommended)
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install dependencies
uv pip install -r requirements-dev.txt
uv pip install -e .

Running Tests and Checks

We provide several ways to run tests and quality checks:

Using Make (recommended):

make test          # Run tests with coverage
make lint          # Run linting with ruff
make typecheck     # Run type checking with mypy
make check-all     # Run all checks (lint, typecheck, test)

Using the development script:

python dev.py          # Run all checks
python dev.py test     # Run tests only
python dev.py lint     # Run linting only
python dev.py typecheck # Run type checking only

Using tools directly:

pytest --cov=json2xml --cov-report=term -xvs tests -n auto
ruff check json2xml tests
mypy json2xml tests

Rust Extension Development

The optional Rust extension (json2xml-rs) provides 29x faster performance. To develop or build the Rust extension:

Prerequisites:

# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install maturin (Rust-Python build tool)
uv pip install maturin

Building the extension:

# Development build (installs in current environment)
cd rust
uv pip install -e .

# Or using maturin directly
maturin develop --release

# Production wheel build
maturin build --release

Running Rust benchmarks:

# After building the extension
python benchmark_rust.py

The Rust code is in rust/src/lib.rs and uses PyO3 for Python bindings.

CLI Usage

The json2xml-py command-line tool provides an easy way to convert JSON to XML from the terminal.

Basic Examples

# Convert a JSON file to XML
json2xml-py data.json

# Convert with custom wrapper element
json2xml-py -w root data.json

# Read JSON from string
json2xml-py -s '{"name": "John", "age": 30}'

# Read from stdin
cat data.json | json2xml-py -

# Output to file
json2xml-py -o output.xml data.json

# Use XPath 3.1 format
json2xml-py -x data.json

# Disable pretty printing and type attributes
json2xml-py --no-pretty --no-type data.json

CLI Options

Input Options:
  -u, --url string        Read JSON from URL
  -s, --string string     Read JSON from string
  [input-file]            Read JSON from file (use - for stdin)

Output Options:
  -o, --output string     Output file (default: stdout)

Conversion Options:
  -w, --wrapper string    Wrapper element name (default "all")
  -r, --root              Include root element (default true)
  -p, --pretty            Pretty print output (default true)
  -t, --type              Include type attributes (default true)
  -i, --item-wrap         Wrap list items in <item> elements (default true)
  -x, --xpath             Use XPath 3.1 json-to-xml format
  -c, --cdata             Wrap string values in CDATA sections
  -l, --list-headers      Repeat headers for each list item

Other Options:
  -v, --version           Show version information
  -h, --help              Show help message

Go Version

A Go port of this library is available at json2xml-go.

Install the Go CLI:

go install github.com/vinitkumar/json2xml-go/cmd/json2xml@latest

The Go version provides the same features and a native compiled binary for maximum performance.

Rust Extension (PyO3)

For users who need maximum performance within Python, json2xml includes an optional native Rust extension built with PyO3:

pip install json2xml[fast]

Rust vs Pure Python Performance:

Test Case

Pure Python

Rust Extension

Speedup

Small JSON (47 bytes)

40µs

1.5µs

27x

Medium JSON (3.2 KB)

2.1ms

71µs

30x

Large JSON (32 KB)

21ms

740µs

28x

Very Large JSON (323 KB)

213ms

7.5ms

28x

Usage with Rust Extension:

# Automatic backend selection (recommended)
from json2xml.dicttoxml_fast import dicttoxml, get_backend

print(f"Using backend: {get_backend()}")  # 'rust' or 'python'

data = {"name": "John", "age": 30}
xml_bytes = dicttoxml(data)

The dicttoxml_fast module automatically uses the Rust backend when available and falls back to pure Python for unsupported features (like xpath_format, xml_namespaces, or custom item_func).

Platform Support:

Pre-built wheels are available for:

  • Linux (x86_64, aarch64)

  • macOS (x86_64, arm64/Apple Silicon)

  • Windows (x86_64)

For other platforms, the pure Python version is used automatically.

Performance Benchmarks

Comprehensive benchmarks comparing all implementations (Apple Silicon, January 2026):

Test Case

Python

Rust

Go

Zig

Best

Small (47B)

40µs

1.5µs

4.6ms

3.7ms

Rust (28x)

Medium (3.2KB)

2.1ms

71µs

4.1ms

3.3ms

Rust (30x)

Large (32KB)

21ms

740µs

4ms

6.1ms

Rust (28x)

Very Large (323KB)

213ms

7.5ms

4.4ms

33ms

Go (48x)

Key Findings:

  • Rust extension: ~28x faster than Python, zero overhead (best for Python users)

  • Go CLI: 48x faster for large files (300KB+), but has ~4ms startup overhead

  • Zig CLI: 3-6x faster for medium-large files

Recommendation by Use Case:

  • Python library calls: Use pip install json2xml[fast] (Rust, 28x faster)

  • Large file CLI processing: Use json2xml-go (Go, 48x for 300KB+)

  • Pure Python required: Use pip install json2xml

For detailed benchmarks, see BENCHMARKS.md.

Other Implementations

This library is also available in other languages:

Help and Support to maintain this project

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

json2xml-6.0.3.tar.gz (61.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

json2xml-6.0.3-py3-none-any.whl (22.7 kB view details)

Uploaded Python 3

File details

Details for the file json2xml-6.0.3.tar.gz.

File metadata

  • Download URL: json2xml-6.0.3.tar.gz
  • Upload date:
  • Size: 61.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for json2xml-6.0.3.tar.gz
Algorithm Hash digest
SHA256 9b6ff511b99b463e3a3deb1246d640625e0f1d5ede1ccff4ce4a2c010cc14f75
MD5 0d74d8037085d221cb529df9d221d2db
BLAKE2b-256 dc07efb074e81a082a4dcb25492db538292758c7d8cf9359adff1f85c3dfa497

See more details on using hashes here.

File details

Details for the file json2xml-6.0.3-py3-none-any.whl.

File metadata

  • Download URL: json2xml-6.0.3-py3-none-any.whl
  • Upload date:
  • Size: 22.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for json2xml-6.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 20eada6031a30b99968fe345f7240a3dd7a57f8dc46a58eddd5119e9893d0714
MD5 2c5dceb42c19b20c3563bc71d234d5ed
BLAKE2b-256 713107d2e91c606da8189800e2979282d38d73ddf7aa0bcf563887170dcf80f1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page