japyd
"JSON:API, Pydantically simple."
Automate JSON:API relationships with Pydantic. No manual mapping, just clean code.
Japyd: Core Value Propositions
Japyd is a Python toolkit designed to simplify the interaction with JSON:API, a specification for building APIs in JSON. It provides a set of utilities to facilitate the creation, manipulation, and validation of JSON:API resources and requests.
Build JSON:API Relational Structures from Pydantic Models
Native Pydantic Integration: Automatically generates JSON:API-compliant resources and relationships from Pydantic models, eliminating boilerplate.
Relationship Management: Supports to-one, to-many, and included resources, fully compliant with the JSON:API specification.
Smart Serialization: Converts Pydantic objects into valid JSON:API documents, handling attributes, relationships, and metadata seamlessly.
Parse JSON:API Query Parameters (Dotnet-style Syntax)
Advanced Query Parsing: Supports JSON:API.NET-style query parameters, including filtering, sorting, pagination, sparse fieldsets, and inclusion.
Built-in Validation: Ensures query parameters are syntactically correct and consistent.
- Filtering: filter[name]=Guillaume
- Sorting: sort=-created,title
- Pagination: page[number]=1&page[size]=10
- Sparse Fieldsets: fields[articles]=title,author
- Inclusion: include=author,comments
Flask Extension for JSON:API Response Formatting
Ready-to-use Flask Integration: Provides a Flask extension to automatically encapsulate responses in JSON:API format, including:
- Resources (data, relationships, attributes)
- Pagination (links, page metadata)
- Errors (standardized JSON:API error objects)
Simplified Endpoints: Reduces manual response formatting, ensuring compliance with JSON:API standards.
Relationship decomposition
To automate and standardize the definition of relationships in our JSON:API implementation, we leveraged Pydantic’s
data model.
This approach allowed us to dynamically infer relationships between resources without manually declaring them for each
object type.
The principle is as follows:
- A Pydantic model represents a resource (e.g., JSON:API Resource Object).
- If an attribute of this model is itself a Pydantic object (or a list of Pydantic objects), it is automatically
interpreted as a
relationshipin the JSON:API response. - If the attribute is a primitive type (string, integer, boolean, or event dict etc.), it is treated as a standard
attribute.
Usage
Serialization
Define your data models in Pydantic, let japyd automatically handle serialization—including relationships and included resources—and expose a standard-compliant JSON:API with Flask in just a few lines of code.
import typing as t
import pytest
from flask import Flask
from flask_pydantic import validate
from japyd import JsonApiBaseModel
from japyd import JsonApiQueryModel
from japyd import TopLevel
class Product(JsonApiBaseModel):
jsonapi_type: t.ClassVar[str] = "product"
id: str
price: float
class Order(JsonApiBaseModel):
jsonapi_type: t.ClassVar[str] = "order"
id: str
customer_id: str
items: list[Product] # This field will be 'relationship' in JSON:API
status: str # This field will be classical 'attribute'
app = Flask(__name__)
@app.route("/orders/<order_id>")
@validate(exclude_none=True)
def get_order(order_id, query: JsonApiQueryModel):
order = Order(id=order_id, customer_id="123", items=[Product(id="1", price=100.0)], status="open")
return query.one_or_none(order)
@pytest.fixture()
def client():
return app.test_client()
def test_request(client):
response = client.get("/orders/3?include=items")
top = TopLevel.model_validate(response.json)
assert top.data.id == "3"
assert top.data.attributes['status'] == 'open'
assert len(top.data.relationships['items'].data) == 1
assert top.included[0].type == "product"
You can bypass this behavior by annotationg the field as follow:
items: Annotated[list[Product], 'as_attribute'] # This field will be now an 'attribute' in JSON:API
Deserialization
Deserialization of JSON:API resource objects into flat dictionaries is handled by the flatten_resource function. This function extracts resource attributes along with the id and type fields, and can optionally flatten nested relationships using a pattern parameter.
from japyd import TopLevel, flatten_resource, extract_relationship
# Example: flatten a resource with nested relationships
response = client.get("/orders/3?include=items")
top = TopLevel.model_validate(response.json)
# Flatten the resource to a dictionary
flattened = flatten_resource(top.data)
# Result: {"type": "order", "id": "3", "customer_id": "123", "status": "open"}
# Flatten with nested relationships using pattern
flattened_with_items = flatten_resource(
top.data,
toplevel=top,
pattern="items"
)
# Result: {"type": "order", "id": "3", "customer_id": "123", "status": "open",
# "items": [{"type": "product", "id": "1", "price": 100.0}]}
Filtering
The complete filtering syntax of JsonApiDotNetCore is supported
References
japyd (JsonApi PYDantic) is a coherent and powerful composition of :
- Pydantic and its Flask extension Flask-Pydantic
- Filtering syntax defined in the dotnet implementation JsonApiDotNetCore.
- Simple relationship extraction and other structure manipulations.
🚀 Looking for Contributors
We’re actively seeking developers, testers, and open-source enthusiasts to help us build and improve japyd. Whether you’re passionate about data validation, API design, or just want to contribute to an innovative open-source project, your help is welcome! Check out our contribution guidelines and open issues to get started. Let’s shape the future of Python APIs together! 💻✨
Metadata
Release files for japyd 1.1.19
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| japyd-1.1.19.tar.gz | 16.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| japyd-1.1.19-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 32.0 kB
Release files / japyd-1.1.19.tar.gz
| Download URL | japyd-1.1.19.tar.gz |
|---|---|
| Size | 16.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a88c8a4cf6497e83d20d59bc2674ff6cf0fa9386f26b9d433cd2c7e9fb35d8ea
|
|
BLAKE2b-256 checksum How to use checksums |
3db722ce7c248066d4c5facf51bbfe8956d4e2a406900904d4fd9b72f6be7dcb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
pdm/2.28.2 CPython/3.12.14 Linux/6.17.0-1022-azure
|
Release files / japyd-1.1.19-py3-none-any.whl
| Download URL | japyd-1.1.19-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e16ce4c0f61d298660443bced521874df45ac36c69b33822aa62d2ace61e84cc
|
|
BLAKE2b-256 checksum How to use checksums |
a1750408b0cbfda063cb6f17ae3181e4bc6320769f45052b52ef0f2da5379832
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
pdm/2.28.2 CPython/3.12.14 Linux/6.17.0-1022-azure
|