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
BaseModelto 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.Functionssubclass - Filter expressions, multi-select hash/list, pipe expressions, wildcards, and or-expressions
- Solid error handling with
ConfigurationError,MappingError, andFieldMappingError– 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
979389c244f748100a71243f99a9d6f8d0427cd2a8ec575c6ebed5a2a1a321ba
|
|
| MD5 |
68da7dc939316f0b2d0e5463b7b4fe2c
|
|
| BLAKE2b-256 |
3ca09d9a3ea25631ac33b9dae5f36b54713840ba8444852c879d2f3fea366034
|
Provenance
The following attestation bundles were made for spaghettimap-0.4.0.tar.gz:
Publisher:
ci-cd.yml on mfowlerrr/spaghettimap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spaghettimap-0.4.0.tar.gz -
Subject digest:
979389c244f748100a71243f99a9d6f8d0427cd2a8ec575c6ebed5a2a1a321ba - Sigstore transparency entry: 1044567219
- Sigstore integration time:
-
Permalink:
mfowlerrr/spaghettimap@b12e9abd5ce61873516527c1c6c4467f4c26f8e9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mfowlerrr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@b12e9abd5ce61873516527c1c6c4467f4c26f8e9 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f48bb229c94acfe79f7e3a2fe8aad39588b0c1a423bf3ec5cbf01d5d2b2feb3
|
|
| MD5 |
164987a662c6666610ed07140c2737ec
|
|
| BLAKE2b-256 |
c343954756168942585ef8a4d414ef064ec961089248331e43dd5cb56521a16f
|
Provenance
The following attestation bundles were made for spaghettimap-0.4.0-py3-none-any.whl:
Publisher:
ci-cd.yml on mfowlerrr/spaghettimap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spaghettimap-0.4.0-py3-none-any.whl -
Subject digest:
0f48bb229c94acfe79f7e3a2fe8aad39588b0c1a423bf3ec5cbf01d5d2b2feb3 - Sigstore transparency entry: 1044567266
- Sigstore integration time:
-
Permalink:
mfowlerrr/spaghettimap@b12e9abd5ce61873516527c1c6c4467f4c26f8e9 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mfowlerrr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci-cd.yml@b12e9abd5ce61873516527c1c6c4467f4c26f8e9 -
Trigger Event:
push
-
Statement type: