Skip to main content

natizon

natizon is a pure Python parser and serializer for ZON (Zig Object Notation). It converts ZON text directly into standard Python types, and serializes Python objects back into valid ZON — all without intermediate AST objects or wrapper layers. Its API is modeled after the standard library's json module, offering loads() and dumps() as the primary entry points.

Built on Lark, the library handles the full ZON grammar, including structs, arrays, enum literals, multiline strings, hexadecimal and float literals, and quoted identifiers.

[!NOTE] natizon is intentionally a little more forgiving than Zig's own std.zon parser. This leniency makes it easier to consume real-world ZON data in Python without friction.

For example, unquoted Zig keywords like if or fn parse just fine — but dumps() always normalizes them to .@"if" and .@"fn" for strict compatibility when you write back out.

API Overview

Function Signature Description
loads (zon_str, *, use_tuples=False, empty_mode=DICT) → dict Parse ZON string to Python dicts/lists.
dumps (obj, *, indent=None, sort_keys=False) → str Serialize Python object to ZON string.
validate_zon_serializable (obj) → None Validate an object is ZON-serializable; raises TypeError or ValueError.

Full type mapping reference →

Installation

pip install natizon

Or:

uv add natizon

Usage

natizon exposes loads() and dumps() functions that work similarly to the standard library's json module.

[!TIP] Looking to parse build.zig.zon?

Check out this Python script for parsing and validating build.zig.zon to see how to:

  • load Zig 0.16 package metadata using natizon,
  • validate fields with Pydantic,
  • and print a pretty JSON dump using Rich.

Parsing

import natizon

zon_data = r"""
.{
    .package_name = "network_tools",
    .version = "2.1.0",
    .supported_platforms = .{ .linux, .macos, .windows },
    .dependencies = .{
        .lib_a = .{ .url = "https://server.com/a.tar" },
        .lib_b = .{ .path = "../local_b" }
    }
}
"""

# Parses directly into standard Python dicts and lists
parsed_data = natizon.loads(zon_data)

print(parsed_data["package_name"])  # "network_tools"
print(parsed_data["supported_platforms"])  # ["linux", "macos", "windows"]

Serialization

You can serialize standard Python objects back into ZON text using dumps():

from enum import Enum
import natizon


class Difficulty(Enum):
    EASY = "easy"
    HARD = "hard"


game_config = {
    "title": "Neon Dash",
    "difficulty": Difficulty.HARD,
    "player_stats": {"level": 10, "xp": 1500},
}

zon_string = natizon.dumps(game_config, indent=2)
print(zon_string)

Output:

.{
  .title = "Neon Dash",
  .difficulty = .HARD,
  .player_stats = .{
    .level = 10,
    .xp = 1500,
  },
}

[!NOTE] While loads() and dumps() are designed to be compatible, some ZON-specific constructs do not roundtrip exactly:

  • Enum literals (e.g., .linux) are parsed into Python strings and will serialize back as quoted strings ("linux"). If you want to preserve them as ZON Enum literals, convert them to your Enum subclass member (e.g., Color.RED) instead.
  • Enum flags (enum.Flag, enum.IntFlag) are not serializable — their bitwise nature lacks a canonical ZON representation. Convert them to a standard Enum tag, integer, or array before serialization.
  • Char literals (e.g., 'a') are parsed into Python integers and will serialize back as integers (97).
  • Empty arrays ([]) serialize to .{}, which loads() parses as an empty dict by default. Use EmptyContainerMode.SEQUENCE if you need them to parse back as lists or tuples.

Advanced Usage

Validation

dumps() automatically validates your data before serialization. If you need to check whether an object is serializable without triggering the full serialization process, use validate_zon_serializable():

from natizon import validate_zon_serializable

user_settings = {
    "theme": "dark",
    "font_size": 14,
    "notifications": True,
}

# Raises TypeError if the object is not serializable,
# or ValueError if a circular reference is detected.
try:
    validate_zon_serializable(user_settings)
    print("Data is valid!")
except (TypeError, ValueError) as e:
    print(f"Validation failed: {e}")

Custom Serialization

Implement the ZonEncodable protocol on your own classes by defining a to_zon() method that returns a ZonSerializable type:

from dataclasses import dataclass
import natizon
from natizon import ZonSerializable


@dataclass
class ByteSize:
    bytes: int

    def to_zon(self) -> ZonSerializable:
        return f"{self.bytes}B"


data = {
    "cache_limit": ByteSize(1024),
    "buffer_size": ByteSize(2048),
}

zon_string = natizon.dumps(data, indent=2)
print(zon_string)

Output:

.{
  .cache_limit = "1024B",
  .buffer_size = "2048B",
}

[!IMPORTANT] If an object implements the ZonEncodable protocol, dumps() always prefers its to_zon() method over built-in serialization for that object's actual type. A subclass of str, int, or Enum that defines to_zon() is serialized as whatever to_zon() returns — not as a string, integer, or enum literal.

License

This project is licensed under the Apache License 2.0. See the LICENSES directory for the full license text.

Download files

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

Source Distribution

natizon-0.4.3.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

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

natizon-0.4.3-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file natizon-0.4.3.tar.gz.

File metadata

  • Download URL: natizon-0.4.3.tar.gz
  • Upload date:
  • Size: 20.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for natizon-0.4.3.tar.gz
Algorithm Hash digest
SHA256 55df867785e04fa4d795fa0c6e7ce5ab5a0fc7fa1688ae6fbd96ceabc95f9e04
MD5 65b4d92f843376185b1a179516ec512d
BLAKE2b-256 c4aeeb5f17e5dfdb6605e1a3aec167d1a46f6795b4ac18342ff086ef1348ef79

See more details on using hashes here.

Provenance

The following attestation bundles were made for natizon-0.4.3.tar.gz:

Publisher: release.yml on BratishkaErik/natizon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file natizon-0.4.3-py3-none-any.whl.

File metadata

  • Download URL: natizon-0.4.3-py3-none-any.whl
  • Upload date:
  • Size: 22.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for natizon-0.4.3-py3-none-any.whl
Algorithm Hash digest
SHA256 9e94379cd57ee39420b0ec664b8268d115296419123fe3c59225d443a856db23
MD5 bbef4fda93056901a6c6bf10547d939e
BLAKE2b-256 a7a94b4ffa20ba985bcb55b188e9a0000c8b36daa90b32a83d1179323befddd5

See more details on using hashes here.

Provenance

The following attestation bundles were made for natizon-0.4.3-py3-none-any.whl:

Publisher: release.yml on BratishkaErik/natizon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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