Dataglasses: easy creation of dataclasses from JSON, and JSON schemas from dataclasses

Posted by Udzu@reddit | Python | View on Reddit | 37 comments

Links: GitHub, PyPI.

What My Project Does

A small package with just two functions: from_dict to create dataclasses from JSON, and to_json_schema to create JSON schemas for validating that JSON. The first can be thought of as the inverse of dataclasses.asdict.

The package uses the dataclass's type annotations and supports nested structures, collection types, Optional and Union types, enums and Literal types, Annotated types (for property descriptions), forward references, and data transformations (which can be used to handle other types). For more details and examples, including of the generated schemas, see the README.

Here is a simple motivating example:

from dataclasses import dataclass
from dataglasses import from_dict, to_json_schema
from typing import Literal, Sequence

@dataclass
class Catalog:
    items: "Sequence[InventoryItem]"
    code: int | Literal["N/A"]

@dataclass
class InventoryItem:
    name: str
    unit_price: float
    quantity_on_hand: int = 0

value = { "items": [{ "name": "widget", "unit_price": 3.0}], "code": 99 }

# convert value to dataclass using from_dict (raises if value is invalid)
assert from_dict(Catalog, value) == Catalog(
    items=[InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=0)], code=99
)

# generate JSON schema to validate against using to_json_schema
schema = to_json_schema(Catalog)
from jsonschema import validate
validate(value, schema)

Target Audience

The package's current state (small and simple, but also limited and unoptimized) makes it best suited for rapid prototyping and scripting. Indeed, I originally wrote it to save myself time while developing a simple script.

That said, it's fully tested (with 100% coverage enforced) and once it has been used in anger (and following any change suggestions) it might be suitable for production code too. The fact that it is so small (two functions in one file with no dependencies) means that it could also be incorporated into a project directly.

Comparison

pydantic is more complex to use and doesn't work on built-in dataclasses. But it's also vastly more suitable for complex validation or high performance.

dacite doesn't generate JSON schemas. There are also some smaller design differences: dataglasses transformations can be applied to specific dataclass fields, enums are handled by default, non-standard generic collection types are not handled by default, and Optional type fields with no defaults are not considered optional in inputs.

Tooling

As an aside, one of the reasons I bothered to package this up from what was otherwise a throwaway project was the chance to try out uv and ruff. And I have to report that so far it's been a very pleasant experience!