Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 03.02: JSON in, JSON out, and the encoding boundary

JSON has no date type and no decimal type, and both are things you will want to send.

The serialisation boundary

An endpoint returning a date and a Decimal, and what arrives as JSON.

The code shows the types on both sides.

from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
from datetime import date
from decimal import Decimal

app = FastAPI()


class Invoice(BaseModel):
    id: str
    issued: date
    amount: Decimal


@app.get("/invoice")
def get_invoice() -> Invoice:
    return Invoice(id="INV-1", issued=date(2026, 6, 14), amount=Decimal("240.50"))


client = TestClient(app)
body = client.get("/invoice").json()
print("JSON sent to the client:", body)
for key, value in body.items():
    print(f"   {key:8} {type(value).__name__}")

print("\ndate became a string; Decimal became a string too, not a float")

# JSON has no date and no decimal type. FastAPI serialises both to strings,
# which preserves precision -- a float would not. The client has to parse them
# back, so the format is part of your contract.

The date becomes a string in ISO format. The Decimal also becomes a string, not a float - which preserves the exact value, because a float cannot represent many decimal amounts precisely.

That choice matters for money. A float round-trip can change 240.50 into something that is not 240.50, and the error appears in a reconciliation weeks later.

The mistake this prevents

The mistake is typing money as float because it looks numeric. Use Decimal and accept the string on the wire - the alternative is a value that is nearly right, which is the worst kind of wrong for money.

Takeaway

JSON has no date or decimal type. FastAPI serialises both to strings; use Decimal for money so precision survives the round trip.