Skip to main content

Map Pydantic models safely, using JMESPath

Project description

spaghettimap

A Python library for pydantic model-to-model conversion powered by JMESPath.

Features

  • Map any pydantic BaseModel to another using a declarative schema
  • Schema values can be JMESPath expressions, Python callables, or a dict combining both with an optional transform
  • Full support for all JMESPath built-in functions (length, sort, max_by, contains, join, keys, to_string, …)
  • Custom JMESPath functions via jmespath.functions.Functions subclass
  • Filter expressions, multi-select hash/list, pipe expressions, wildcards, and or-expressions
  • Solid error handling with ConfigurationError, MappingError, and FieldMappingError – all with clear, field-specific messages
  • Fail-fast config checks for invalid JMESPath expressions and schema fields missing from the target model
  • Pydantic validators (@field_validator, @model_validator) and type coercion run on the target model automatically
  • map_many() for batch conversion of model lists

Installation

pip install spaghettimap
# or with uv
uv add spaghettimap

Quick Start

from pydantic import BaseModel
from spaghettimap import Mapper, MappingConfig

class Source(BaseModel):
    first_name: str
    last_name: str
    contact: dict  # {"email": "...", "phone": "..."}
    tags: list[dict]  # [{"name": "...", "weight": 1.0}]

class Target(BaseModel):
    full_name: str
    email: str
    tag_count: int
    upper_name: str

mapper = Mapper()
mapper.add_config(
    MappingConfig(
        from_type=Source,
        to_type=Target,
        schema={
            # Python callable
            "full_name": lambda d: f"{d['first_name']} {d['last_name']}",
            # Nested JMESPath expression
            "email": "contact.email",
            # JMESPath built-in function
            "tag_count": "length(tags)",
            # JMESPath expression + Python transform
            "upper_name": {"expression": "first_name", "transform": str.upper},
        },
    )
)

result: Target = mapper.map(source_instance, Target)

Schema Value Types

Type Description Example
str JMESPath expression "contact.email", "tags[*].name", "length(tags)"
Callable[[dict], Any] Python function receiving the full source dict lambda d: d["x"] + d["y"]
dict {"expression": str|Callable, "transform": Callable} {"expression": "price", "transform": lambda p: f"£{p:.2f}"}

Custom JMESPath Functions

import jmespath.functions
from spaghettimap import Mapper, MappingConfig

class MyFunctions(jmespath.functions.Functions):
    @jmespath.functions.signature({"types": ["string"]})
    def _func_upper(self, value: str) -> str:
        return value.upper()

mapper.add_config(
    MappingConfig(
        from_type=Source,
        to_type=Target,
        schema={"name": "upper(first_name)"},
        custom_functions=MyFunctions(),
    )
)

Batch Mapping

results: list[Target] = mapper.map_many(source_list, Target)

Error Hierarchy

SpaghettimapMapperError
├── ConfigurationError   – invalid config (bad types, missing keys, unregistered pair)
└── MappingError         – runtime mapping failure
    └── FieldMappingError – failure for a specific field (has .field attribute)

Project details


Download files

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

Source Distribution

spaghettimap-0.4.0.tar.gz (6.3 kB view details)

Uploaded Source

Built Distribution

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

spaghettimap-0.4.0-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

File details

Details for the file spaghettimap-0.4.0.tar.gz.

File metadata

  • Download URL: spaghettimap-0.4.0.tar.gz
  • Upload date:
  • Size: 6.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for spaghettimap-0.4.0.tar.gz
Algorithm Hash digest
SHA256 979389c244f748100a71243f99a9d6f8d0427cd2a8ec575c6ebed5a2a1a321ba
MD5 68da7dc939316f0b2d0e5463b7b4fe2c
BLAKE2b-256 3ca09d9a3ea25631ac33b9dae5f36b54713840ba8444852c879d2f3fea366034

See more details on using hashes here.

Provenance

The following attestation bundles were made for spaghettimap-0.4.0.tar.gz:

Publisher: ci-cd.yml on mfowlerrr/spaghettimap

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

File details

Details for the file spaghettimap-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: spaghettimap-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 8.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for spaghettimap-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f48bb229c94acfe79f7e3a2fe8aad39588b0c1a423bf3ec5cbf01d5d2b2feb3
MD5 164987a662c6666610ed07140c2737ec
BLAKE2b-256 c343954756168942585ef8a4d414ef064ec961089248331e43dd5cb56521a16f

See more details on using hashes here.

Provenance

The following attestation bundles were made for spaghettimap-0.4.0-py3-none-any.whl:

Publisher: ci-cd.yml on mfowlerrr/spaghettimap

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 Pingdom Monitoring Sentry Error logging StatusPage Status page