Validation and serialization layer for Azure Functions Python v2 programming model
Project description
Azure Functions Validation
Part of the Azure Functions Python DX Toolkit — a collection of small tools for improving Azure Functions Python developer experience.
Read this in: 한국어 | 日本語 | 简体中文
Validation and serialization for the Azure Functions Python v2 programming model.
Part of the Azure Functions Python DX Toolkit → Bring FastAPI-like developer experience to Azure Functions
Why this exists
Azure Functions Python v2 handlers often drift into the same repeated problems:
- Repeated manual parsing — every handler calls
req.get_json(),req.params.get(), handlesValueErrorindividually - Inconsistent error responses — some handlers return 400, others 422, formats vary across the project
- Missing response contracts — response payloads silently diverge from the intended schema
- No type safety — request data flows through as untyped dicts, bugs surface only at runtime
What it does
- Typed validation — body, query, path, and header parameters validated via Pydantic v2
- Automatic error responses — invalid requests get consistent
400/422JSON error bodies - Response model enforcement — mismatches raise
ResponseValidationError(HTTP 500) - Decorator-first API —
@validate_httpwraps your handler, no boilerplate needed
Before / After
Without this package — manual parsing, manual errors, no contracts:
import json
import azure.functions as func
app = func.FunctionApp()
@app.route(route="users", methods=["POST"])
def create_user(req: func.HttpRequest) -> func.HttpResponse:
try:
body = req.get_json()
except ValueError:
return func.HttpResponse(
json.dumps({"error": "Invalid JSON"}),
status_code=400,
mimetype="application/json",
)
name = body.get("name")
email = body.get("email")
if not name or not isinstance(name, str):
return func.HttpResponse(
json.dumps({"error": "name is required"}),
status_code=400,
mimetype="application/json",
)
if not email or not isinstance(email, str):
return func.HttpResponse(
json.dumps({"error": "email is required"}),
status_code=400,
mimetype="application/json",
)
return func.HttpResponse(
json.dumps({"message": f"Hello {name}", "status": "success"}),
mimetype="application/json",
)
With @validate_http — typed, consistent, contract-enforced:
import azure.functions as func
from pydantic import BaseModel
from azure_functions_validation import validate_http
app = func.FunctionApp()
class CreateUserRequest(BaseModel):
name: str
email: str
class CreateUserResponse(BaseModel):
message: str
status: str = "success"
@app.route(route="users", methods=["POST"])
@validate_http(body=CreateUserRequest, response_model=CreateUserResponse)
def create_user(req: func.HttpRequest, body: CreateUserRequest) -> CreateUserResponse:
return CreateUserResponse(message=f"Hello {body.name}")
Manual parsing and validation disappear from the handler. Error formatting and response contracts — handled.
What you get
Valid request → typed response:
$ curl -s -X POST http://localhost:7071/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}'
{"message": "Hello Alice", "status": "success"}
HTTP 200
Missing required field → automatic error response:
$ curl -s -X POST http://localhost:7071/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice"}'
{
"detail": [
{
"loc": ["email"],
"msg": "Field required",
"type": "missing"
}
]
}
HTTP 422 — standardized error response, automatic
Invalid JSON → clear error:
$ curl -s -X POST http://localhost:7071/api/users \
-H "Content-Type: application/json" \
-d 'not json'
{"detail": [{"loc": [], "msg": "Invalid JSON", "type": "value_error"}]}
HTTP 400
FastAPI comparison
| Feature | FastAPI | azure-functions-validation |
|---|---|---|
| Request body parsing | Built-in via type hints | @validate_http(body=Model) |
| Query/path/header validation | Query(), Path(), Header() |
@validate_http(query=Model, path=Model, headers=Model) |
| Response model | response_model= |
@validate_http(response_model=Model) |
| Validation errors | Automatic 422 | Automatic 422 with {"detail": [...]} |
| Error customization | Exception handlers | ErrorFormatter callback |
Scope
- Azure Functions Python v2 programming model
- HTTP-triggered functions registered on
func.FunctionApp() - Pydantic v2-based request and response validation
This package does not target the legacy function.json-based v1 programming model.
What this package does not do
This package does not own:
- API documentation and spec generation — use
azure-functions-openapi - Runtime exposure or graph deployment — use
azure-functions-langgraph - Project scaffolding — use
azure-functions-scaffold
Features
- Typed body, query, path, and header validation via
@validate_http - Automatic 400 / 422 responses with
{"detail": [...]}envelope - Response model validation — mismatches raise
ResponseValidationError(HTTP 500) - Custom per-handler error formatting via
ErrorFormatter
Package names
Three names cover three different contexts:
| Context | Name |
|---|---|
| GitHub repo | azure-functions-validation-python |
| PyPI package | azure-functions-validation |
| Python import | azure_functions_validation |
The repository carries the -python suffix to mark it as the Python implementation. The PyPI package follows Python ecosystem conventions and is published without the suffix, so installation stays idiomatic: pip install azure-functions-validation. See the FAQ entry for the long version.
Installation
pip install azure-functions-validation
Your Azure Functions app should also include:
azure-functions
azure-functions-validation
For local development:
git clone https://github.com/yeongseon/azure-functions-validation-python.git
cd azure-functions-validation-python
pip install -e .[dev]
Quick Start
import azure.functions as func
from pydantic import BaseModel
from azure_functions_validation import validate_http
class CreateUserRequest(BaseModel):
name: str
email: str
class CreateUserResponse(BaseModel):
message: str
status: str = "success"
app = func.FunctionApp()
@app.function_name(name="create_user")
@app.route(route="users", methods=["POST"], auth_level=func.AuthLevel.ANONYMOUS)
@validate_http(body=CreateUserRequest, response_model=CreateUserResponse)
def create_user(req: func.HttpRequest, body: CreateUserRequest) -> CreateUserResponse:
return CreateUserResponse(message=f"Hello {body.name}")
Start the Functions host locally:
func start
Verify locally and on Azure
After deploying (see docs/deployment.md), the same request produces the same response in both environments.
Local
curl -s http://localhost:7071/api/users \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}'
{"message": "Hello Alice", "status": "success"}
Azure
curl -s "https://<your-app>.azurewebsites.net/api/users" \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}'
{"message": "Hello Alice", "status": "success"}
Invalid requests return the same 400 error in both environments:
Local
curl -s http://localhost:7071/api/users \
-H "Content-Type: application/json" \
-d 'not json'
{"detail": [{"loc": [], "msg": "Invalid JSON", "type": "value_error"}]}
HTTP 400
Azure
curl -s "https://<your-app>.azurewebsites.net/api/users" \
-H "Content-Type: application/json" \
-d 'not json'
{"detail": [{"loc": [], "msg": "Invalid JSON", "type": "value_error"}]}
HTTP 400
Verified against a temporary Azure Functions deployment in koreacentral (Python 3.12, Consumption plan). Response captured and URL anonymized.
When to use
- You have HTTP-triggered Azure Functions that accept JSON request bodies
- You want Pydantic-based validation without writing manual parsing code
- You need consistent error response formats across handlers
- You want response schema enforcement to catch contract drift
Documentation
- Project docs live under
docs/ - Smoke-tested examples live under
examples/ - Product requirements:
PRD.md - Design principles:
DESIGN.md
Ecosystem
This package is part of the Azure Functions Python DX Toolkit.
Design principle: azure-functions-validation owns request/response validation and serialization. azure-functions-openapi owns API documentation and spec generation. azure-functions-langgraph owns LangGraph runtime exposure.
| Package | Role |
|---|---|
| azure-functions-openapi | OpenAPI spec generation and Swagger UI |
| azure-functions-validation | Request/response validation and serialization |
| azure-functions-db | Database bindings for SQL, PostgreSQL, MySQL, SQLite, and Cosmos DB |
| azure-functions-langgraph | LangGraph deployment adapter for Azure Functions |
| azure-functions-scaffold | Project scaffolding CLI |
| azure-functions-logging | Structured logging and observability |
| azure-functions-doctor | Pre-deploy diagnostic CLI |
| azure-functions-durable-graph | Manifest-first graph runtime with Durable Functions (experimental) |
| azure-functions-python-cookbook | Recipes and examples |
For AI Coding Assistants
When integrating with LLM-powered coding assistants, provide these files for context:
llms.txt— Concise index with quick start and API overviewllms-full.txt— Expanded reference with full signatures and patterns
Reference the files at repository root:
- https://github.com/yeongseon/azure-functions-validation-python/blob/main/llms.txt
- https://github.com/yeongseon/azure-functions-validation-python/blob/main/llms-full.txt
Disclaimer
This project is an independent community project and is not affiliated with, endorsed by, or maintained by Microsoft.
Azure and Azure Functions are trademarks of Microsoft Corporation.
License
MIT
Project details
Release history Release notifications | RSS feed
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 azure_functions_validation-0.7.4.tar.gz.
File metadata
- Download URL: azure_functions_validation-0.7.4.tar.gz
- Upload date:
- Size: 109.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9c92d801f4002a68c00fee8d2371fa9dd8f880ba4c060f5b3b406cba058acd04
|
|
| MD5 |
445fe7a63320896dbb4992d2687c799f
|
|
| BLAKE2b-256 |
305414f2dfe1ad3b43345b1b99e2e4e4ac88d6884f2164ff237467358e46f24a
|
Provenance
The following attestation bundles were made for azure_functions_validation-0.7.4.tar.gz:
Publisher:
publish-pypi.yml on yeongseon/azure-functions-validation-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
azure_functions_validation-0.7.4.tar.gz -
Subject digest:
9c92d801f4002a68c00fee8d2371fa9dd8f880ba4c060f5b3b406cba058acd04 - Sigstore transparency entry: 1409464455
- Sigstore integration time:
-
Permalink:
yeongseon/azure-functions-validation-python@375e9d2de0029ed104a7f7a56cd28ea5c2540a01 -
Branch / Tag:
refs/tags/v0.7.4 - Owner: https://github.com/yeongseon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@375e9d2de0029ed104a7f7a56cd28ea5c2540a01 -
Trigger Event:
push
-
Statement type:
File details
Details for the file azure_functions_validation-0.7.4-py3-none-any.whl.
File metadata
- Download URL: azure_functions_validation-0.7.4-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c7f3b17106a9175d6d73e3e000a6399f954044d54d27d48387ebbc7520ea904
|
|
| MD5 |
969b9be7002fd691d5546289d0cd00cd
|
|
| BLAKE2b-256 |
74db3c80417d25f358bf4a826f6978587d013b2ec83504779456c670ffa6cd59
|
Provenance
The following attestation bundles were made for azure_functions_validation-0.7.4-py3-none-any.whl:
Publisher:
publish-pypi.yml on yeongseon/azure-functions-validation-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
azure_functions_validation-0.7.4-py3-none-any.whl -
Subject digest:
3c7f3b17106a9175d6d73e3e000a6399f954044d54d27d48387ebbc7520ea904 - Sigstore transparency entry: 1409464456
- Sigstore integration time:
-
Permalink:
yeongseon/azure-functions-validation-python@375e9d2de0029ed104a7f7a56cd28ea5c2540a01 -
Branch / Tag:
refs/tags/v0.7.4 - Owner: https://github.com/yeongseon
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@375e9d2de0029ed104a7f7a56cd28ea5c2540a01 -
Trigger Event:
push
-
Statement type: