Pattern di Design per API JSON: Costruire API REST Migliori
Un'API ben progettata è un piacere da usare. Una progettata male crea bug, frustrazione e debito tecnico. Questa guida copre pattern collaudati per progettare API REST JSON che siano coerenti, scopribili e mantenibili.
Denominazione delle Risorse
Le risorse sono sostantivi, non verbi. Usa sostantivi plurali per le collezioni e risorse singole tramite ID:
GET /api/users # Lista utenti
POST /api/users # Crea un utente
GET /api/users/123 # Ottieni utente 123
PUT /api/users/123 # Aggiorna utente 123
DELETE /api/users/123 # Elimina utente 123
Convenzioni di denominazione:
- Usa minuscole con trattini:
/api/blog-posts(nonblogPostsoblog_posts) - Annida risorse correlate:
/api/users/123/orders - Limita l'annidamento a 2 livelli:
/api/users/123/orders/456(non più in profondità) - Evita verbi negli URL:
/api/users/123/activateè accettabile per azioni che non mappano a CRUD
Envelope di Risposta
Avvolgi le risposte in un envelope coerente:
{
"data": {
"id": "123",
"type": "user",
"attributes": {
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}
},
"meta": {
"requestId": "req_abc123"
}
}
Per le collezioni:
{
"data": [
{ "id": "123", "name": "Alice" },
{ "id": "456", "name": "Bob" }
],
"meta": {
"total": 142,
"page": 1,
"perPage": 20
}
}
Valida le risposte della tua API con il nostro Validatore JSON per assicurarti che corrispondano al tuo schema.
Paginazione
Tre approcci comuni:
Basata su Offset (Più Semplice)
GET /api/users?page=2&per_page=20
{
"data": [...],
"meta": {
"page": 2,
"perPage": 20,
"total": 142,
"totalPages": 8
}
}
Pro: Semplice, supporta il salto a qualsiasi pagina. Contro: Risultati incoerenti con inserimenti/eliminazioni concorrenti.
Basata su Cursore (Più Affidabile)
GET /api/users?cursor=eyJpZCI6MTIzfQ&limit=20
{
"data": [...],
"meta": {
"hasNext": true,
"nextCursor": "eyJpZCI6MTQzfQ"
}
}
Pro: Coerente con modifiche concorrenti, performante su grandi dataset. Contro: Non può saltare a pagine arbitrarie.
Basata su Keyset (Più Performante)
GET /api/users?after_id=123&limit=20
Usa l'ID dell'ultimo elemento (o altro campo ordinato) per ottenere la pagina successiva. Simile alla paginazione basata su cursore ma con parametri trasparenti.
Raccomandazione: Usa basata su cursore per feed in tempo reale e grandi dataset. Usa basata su offset per dashboard admin dove il salto di pagina è importante.
Filtraggio e Ordinamento
Filtraggio
GET /api/users?status=active&role=admin
GET /api/users?created_after=2024-01-01
GET /api/users?search=alice
Per filtri complessi, considera un parametro di query dedicato:
GET /api/users?filter[status]=active&filter[role]=admin
Ordinamento
GET /api/users?sort=name # Ascendente
GET /api/users?sort=-created_at # Discendente (prefisso con -)
GET /api/users?sort=-created_at,name # Campi multipli
Gestione degli Errori
Risposte di errore coerenti sono critiche per l'usabilità dell'API:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{
"field": "email",
"message": "Must be a valid email address",
"value": "not-an-email"
},
{
"field": "age",
"message": "Must be between 0 and 150",
"value": -5
}
]
},
"meta": {
"requestId": "req_abc123"
}
}
Codici di stato HTTP da usare:
| Codice | Significato | Quando |
|---|---|---|
| 200 | OK | GET, PUT riusciti |
| 201 | Created | POST che ha creato una risorsa |
| 204 | No Content | DELETE riuscito |
| 400 | Bad Request | Errori di validazione |
| 401 | Unauthorized | Auth mancante/non valida |
| 403 | Forbidden | Auth valida, permessi insufficienti |
| 404 | Not Found | La risorsa non esiste |
| 409 | Conflict | Risorsa duplicata, conflitto di versione |
| 422 | Unprocessable | Semanticamente non valido |
| 429 | Too Many Requests | Limite di frequenza superato |
| 500 | Internal Error | Errore server inatteso |
Versionamento
Tre approcci:
Percorso URL (Raccomandato)
GET /api/v1/users
GET /api/v2/users
Pro: Esplicito, facile da routare, facile da testare.
Basato su Header
GET /api/users
Accept: application/vnd.myapi.v2+json
Pro: URL puliti. Contro: Più difficile da testare, meno scopribile.
Parametro Query
GET /api/users?version=2
Pro: Facile da testare. Contro: Semantica dei parametri opzionali.
Raccomandazione: Il versionamento nel percorso URL è la scelta più pratica. È esplicito, cacheable e funziona con ogni strumento HTTP.
Gestione di Date e Orari
Usa sempre ISO 8601 in UTC:
{
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T14:22:33Z",
"expiresAt": "2024-12-31T23:59:59Z"
}
Non usare mai timestamp Unix nelle risposte API — sono ambigui (secondi vs millisecondi) e non leggibili dall'uomo. Per approfondire la gestione dei timestamp, consulta la nostra guida ai Timestamp Unix.
Rate Limiting
Comunica i limiti di frequenza negli header di risposta:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 67
X-RateLimit-Reset: 1705312800
Retry-After: 30
Restituisci 429 Too Many Requests quando il limite viene superato, con un messaggio di errore chiaro e header Retry-After.
HATEOAS (Opzionale ma Potente)
Includi link a risorse e azioni correlate:
{
"data": {
"id": "123",
"name": "Alice",
"links": {
"self": "/api/users/123",
"orders": "/api/users/123/orders",
"avatar": "/api/users/123/avatar"
}
}
}
Questo rende la tua API auto-documentante e riduce la costruzione di URL lato client.
FAQ
Dovrei usare la specifica JSON:API o progettare il mio formato?
La specifica JSON:API (jsonapi.org) fornisce uno standard completo, ma può essere verbosa per API semplici. Per la maggior parte dei progetti, progettare un formato personalizzato più semplice seguendo i pattern in questa guida è più pratico. Usa JSON:API se hai bisogno di librerie client automatiche e uno standard rigoroso.
Come dovrei gestire gli aggiornamenti parziali (PATCH vs PUT)?
Usa PUT per la sostituzione completa della risorsa (il client invia tutti i campi). Usa PATCH per aggiornamenti parziali (il client invia solo i campi modificati). PATCH con JSON Merge Patch (RFC 7396) è l'approccio più semplice: invia un oggetto JSON con solo i campi da aggiornare, e null per rimuovere un campo.
Risorse Correlate
- Formattatore JSON — Formatta le risposte API per la leggibilità
- Guida alla Validazione JSON Schema — Valida i payload API con JSON Schema
- Token JWT Spiegati — Proteggi le tue API con JSON Web Token