Skip to main content

japyd

"JSON:API, Pydantically simple."

Automate JSON:API relationships with Pydantic. No manual mapping, just clean code.

Tests Codecov PyPI License: MIT Python Maintenance Open Source Code style: black

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 relationship in 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 :

  1. Pydantic and its Flask extension Flask-Pydantic
  2. Filtering syntax defined in the dotnet implementation JsonApiDotNetCore.
  3. 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.20

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for japyd 1.1.20
File Size Uploaded
japyd-1.1.20.tar.gz 16.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for japyd 1.1.20
File Interpreter ABI Platform
japyd-1.1.20-py3-none-any.whl Python 3 none any Details

Total release size: 32.1 kB

Release files / japyd-1.1.20.tar.gz

Download URL japyd-1.1.20.tar.gz
Size 16.3 kB
Tags Source
SHA-256 checksum
How to use checksums
586e0d60b93c4c246c229dca15712c213ba0e9e4a9239fdb1184018ab262921b
BLAKE2b-256 checksum
How to use checksums
24179c8784d2bb2c146283c3d07b3c923e611808a67d6b83b98bdb2a28bc6ee6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.29.0 CPython/3.12.14 Linux/6.17.0-1022-azure

Release files / japyd-1.1.20-py3-none-any.whl

Download URL japyd-1.1.20-py3-none-any.whl
Size 15.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
489b38dcd03f5f18adbf2dcbbdce9299206d66183b363e8d075c57f2227201d3
BLAKE2b-256 checksum
How to use checksums
6e23492f7db019516efdcc65ca4d292ec96e2565c4fa581491c363fccdce1e3a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via pdm/2.29.0 CPython/3.12.14 Linux/6.17.0-1022-azure

Release history Release notifications | RSS feed

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page