Skip to content

Getting Started

This page gets you from plain RFC 6902 patching to a real FastAPI PATCH contract with the fewest moving parts.

Install

pip install jsonpatchx

Optional FastAPI helpers come later:

pip install "jsonpatchx[fastapi]"

You do not need that extra just to use JsonPatch or JsonPatchFor[...].

1. Apply a plain RFC 6902 patch

from jsonpatchx import JsonPatch

doc = {
    "name": "Ada",
    "roles": ["engineer"],
    "active": True,
}

patch = JsonPatch(
    [
        {"op": "replace", "path": "/name", "value": "Ada Lovelace"},
        {"op": "add", "path": "/roles/-", "value": "maintainer"},
    ]
)

updated = patch.apply(doc)

That is ordinary JSON Patch.

JsonPatch is Pydantic-backed, so the patch document is parsed and validated before it is applied. If you already have JSON text, use JsonPatch.from_string(...) and apply it the same way.

2. Turn the same RFC ops into a FastAPI contract

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, EmailStr

from jsonpatchx import JsonPatchFor


class User(BaseModel):
    id: int
    email: EmailStr
    active: bool


app = FastAPI()


@app.patch("/users/{user_id}", response_model=User)
def patch_user(user_id: int, patch: JsonPatchFor[User]) -> User:
    user = load_user(user_id)
    if user is None:
        raise HTTPException(status_code=404, detail="user not found")

    updated = patch.apply(user)
    save_user(user_id, updated)
    return updated

The request body on the wire is still standard JSON Patch:

PATCH /users/1
Content-Type: application/json-patch+json

[
  {"op": "replace", "path": "/email", "value": "ada@example.com"},
  {"op": "replace", "path": "/active", "value": false}
]

What changed is the contract around it.

JsonPatchFor[User] means:

  • the request body is parsed as a patch document, not a bare list[dict]
  • the operations are validated before mutation
  • the patched result is validated as User
  • the route gets a real PATCH request schema instead of undocumented patch dicts

That is the smallest useful JsonPatchX route.

What the first two examples are really showing

The first example proves that JsonPatchX is happy to be just an RFC 6902 library.

The second example proves that you do not need to buy into custom operations, JSONPath, or helper classes just to get value from it. One type annotation is enough to make PATCH part of a real FastAPI contract.

The next page stays with that idea and shows where the optional FastAPI helper layer fits.