← Torna al Blog

API JSON e servizi REST: Guida completa per sviluppatori

Guida completa alle API JSON e REST: metodi HTTP, autenticazione, best practices, esempi pratici con fetch e axios. Impara a creare e consumare API moderne.

Big JSON Team16 min di letturaprogramming
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

16 min di lettura

# API JSON e servizi REST: Guida completa per sviluppatori

Le API REST con JSON sono il fondamento del web moderno. Questa guida completa ti insegnerà tutto ciò che devi sapere per creare e consumare API JSON professionalmente.

Cos'è una API REST?

REST (Representational State Transfer) è uno stile architetturale per API web che usa:

  • HTTP methods: GET, POST, PUT, DELETE
  • JSON: Formato di scambio dati
  • Stateless: Ogni richiesta è indipendente
  • Resource-based: URL rappresentano risorse

Esempio API REST

GET    /api/users          # Lista utenti

GET /api/users/123 # Utente specifico

POST /api/users # Crea utente

PUT /api/users/123 # Aggiorna utente

DELETE /api/users/123 # Elimina utente

Metodi HTTP

GET - Recuperare dati

// Fetch API

fetch('https://api.example.com/users/123')

.then(response => response.json())

.then(user => {

console.log(user);

// { id: 123, nome: "Marco", email: "marco@example.com" }

});

// Async/await

async function getUser(id) {

const response = await fetch(https://api.example.com/users/${id});

const user = await response.json();

return user;

}

POST - Creare risorse

const newUser = {

nome: "Marco",

email: "marco@example.com",

password: "SecurePass123"

};

fetch('https://api.example.com/users', {

method: 'POST',

headers: {

'Content-Type': 'application/json',

},

body: JSON.stringify(newUser)

})

.then(response => response.json())

.then(data => {

console.log('Utente creato:', data);

// { id: 456, nome: "Marco", ... }

});

PUT - Aggiornare risorse

const updatedUser = {

nome: "Marco Rossi",

email: "marco.rossi@example.com"

};

fetch('https://api.example.com/users/123', {

method: 'PUT',

headers: {

'Content-Type': 'application/json',

},

body: JSON.stringify(updatedUser)

})

.then(response => response.json())

.then(data => console.log('Utente aggiornato:', data));

PATCH - Aggiornamento parziale

// Aggiorna solo l'email

const patch = {

email: "nuovo.email@example.com"

};

fetch('https://api.example.com/users/123', {

method: 'PATCH',

headers: {

'Content-Type': 'application/json',

},

body: JSON.stringify(patch)

})

.then(response => response.json())

.then(data => console.log('Email aggiornata:', data));

DELETE - Eliminare risorse

fetch('https://api.example.com/users/123', {

method: 'DELETE'

})

.then(response => {

if (response.ok) {

console.log('Utente eliminato');

}

});

Codici di stato HTTP

2xx Success

200 OK              # Richiesta riuscita

201 Created # Risorsa creata

204 No Content # Successo senza body

3xx Redirection

301 Moved Permanently

302 Found

304 Not Modified

4xx Client Error

400 Bad Request     # Dati invalidi

401 Unauthorized # Non autenticato

403 Forbidden # Non autorizzato

404 Not Found # Risorsa non trovata

422 Unprocessable # Validazione fallita

5xx Server Error

500 Internal Server Error

502 Bad Gateway

503 Service Unavailable

Gestione errori completa

async function apiCall(url, options = {}) {

try {

const response = await fetch(url, options);

// Gestisci errori HTTP

if (!response.ok) {

const error = await response.json();

throw new Error(HTTP ${response.status}: ${error.message});

}

// Parse JSON

const data = await response.json();

return { success: true, data };

} catch (error) {

console.error('API Error:', error);

return {

success: false,

error: error.message

};

}

}

// Uso

const result = await apiCall('https://api.example.com/users');

if (result.success) {

console.log('Dati:', result.data);

} else {

console.error('Errore:', result.error);

}

Autenticazione

1. API Key

fetch('https://api.example.com/data', {

headers: {

'X-API-Key': 'your-api-key-here'

}

})

.then(response => response.json())

.then(data => console.log(data));

2. Bearer Token

const token = 'your-jwt-token';

fetch('https://api.example.com/protected', {

headers: {

'Authorization': Bearer ${token}

}

})

.then(response => response.json())

.then(data => console.log(data));

3. Basic Auth

const username = 'user';

const password = 'pass';

const credentials = btoa(${username}:${password});

fetch('https://api.example.com/data', {

headers: {

'Authorization': Basic ${credentials}

}

})

.then(response => response.json());

Axios - Cliente HTTP avanzato

const axios = require('axios');

// GET request

const user = await axios.get('https://api.example.com/users/123');

console.log(user.data);

// POST request

const newUser = await axios.post('https://api.example.com/users', {

nome: "Marco",

email: "marco@example.com"

});

// PUT request

const updated = await axios.put('https://api.example.com/users/123', {

nome: "Marco Rossi"

});

// DELETE request

await axios.delete('https://api.example.com/users/123');

Axios instance con configurazione

const api = axios.create({

baseURL: 'https://api.example.com',

timeout: 5000,

headers: {

'Content-Type': 'application/json',

'Authorization': Bearer ${token}

}

});

// Interceptors per logging

api.interceptors.request.use(request => {

console.log('Request:', request.method.toUpperCase(), request.url);

return request;

});

api.interceptors.response.use(

response => {

console.log('Response:', response.status);

return response;

},

error => {

console.error('Error:', error.message);

return Promise.reject(error);

}

);

// Uso

const users = await api.get('/users');

const newUser = await api.post('/users', { nome: "Marco" });

Paginazione

Query parameters

// GET /api/users?page=2&limit=10

async function getUsers(page = 1, limit = 10) {

const url = new URL('https://api.example.com/users');

url.searchParams.append('page', page);

url.searchParams.append('limit', limit);

const response = await fetch(url);

return response.json();

}

// Response

{

"data": [...], // 10 utenti

"pagination": {

"page": 2,

"limit": 10,

"total": 95,

"pages": 10

}

}

Cursor-based

// GET /api/users?cursor=abc123

{

"data": [...],

"pagination": {

"next_cursor": "xyz789",

"has_more": true

}

}

Filtri e ordinamento

// GET /api/users?role=admin&sort=-created_at&filter[active]=true

const url = new URL('https://api.example.com/users');

url.searchParams.append('role', 'admin');

url.searchParams.append('sort', '-created_at');

url.searchParams.append('filter[active]', 'true');

const response = await fetch(url);

const users = await response.json();

Versionamento API

1. URL versioning

https://api.example.com/v1/users

https://api.example.com/v2/users

2. Header versioning

fetch('https://api.example.com/users', {

headers: {

'Accept-Version': 'v2'

}

})

3. Query parameter

https://api.example.com/users?version=2

Rate limiting

Gestione rate limits

async function apiCallWithRetry(url, options = {}, maxRetries = 3) {

for (let i = 0; i < maxRetries; i++) {

try {

const response = await fetch(url, options);

// Check rate limit headers

const remaining = response.headers.get('X-RateLimit-Remaining');

const reset = response.headers.get('X-RateLimit-Reset');

if (response.status === 429) {

const retryAfter = response.headers.get('Retry-After') || 60;

console.log(Rate limited. Retry after ${retryAfter}s);

await new Promise(resolve => setTimeout(resolve, retryAfter 1000));

continue;

}

if (response.ok) {

return await response.json();

}

throw new Error(HTTP ${response.status});

} catch (error) {

if (i === maxRetries - 1) throw error;

await new Promise(resolve => setTimeout(resolve, 1000 (i + 1)));

}

}

}

Webhook

Ricevere webhook (Express)

const express = require('express');

const app = express();

app.use(express.json());

app.post('/webhooks/payment', (req, res) => {

const event = req.body;

console.log('Webhook ricevuto:', event.type);

switch (event.type) {

case 'payment.succeeded':

// Gestisci pagamento riuscito

console.log('Pagamento:', event.data);

break;

case 'payment.failed':

// Gestisci pagamento fallito

console.log('Pagamento fallito:', event.data);

break;

}

// Rispondi 200 per confermare ricezione

res.json({ received: true });

});

app.listen(3000);

Best practices

1. Usa metodi HTTP corretti

// ✅ Corretto

GET /api/users // Ottieni lista

POST /api/users // Crea nuovo

PUT /api/users/123 // Aggiorna completamente

PATCH /api/users/123 // Aggiorna parzialmente

DELETE /api/users/123 // Elimina

// ❌ Da evitare

GET /api/createUser

POST /api/getUsers

2. Usa nomi di risorsa plurali

✅ /api/users

✅ /api/products

✅ /api/orders

❌ /api/user

❌ /api/product

3. Usa nesting per relazioni

GET /api/users/123/orders        # Ordini dell'utente

GET /api/users/123/orders/456 # Ordine specifico

POST /api/users/123/orders # Crea ordine per utente

4. Restituisci codici status appropriati

// POST - Creazione riuscita

res.status(201).json({ id: 123, nome: "Marco" });

// PUT - Aggiornamento

res.status(200).json({ id: 123, nome: "Marco Rossi" });

// DELETE - Eliminazione

res.status(204).send(); // No content

// Errore validazione

res.status(422).json({

error: "Validazione fallita",

details: [...]

});

// Non trovato

res.status(404).json({

error: "Risorsa non trovata"

});

5. Fornisci messaggi di errore chiari

// ✅ Errore chiaro

{

"error": {

"code": "VALIDATION_ERROR",

"message": "Dati non validi",

"details": [

{

"field": "email",

"message": "Email non valida"

},

{

"field": "password",

"message": "Password troppo corta (minimo 8 caratteri)"

}

]

}

}

// ❌ Errore vago

{

"error": "Bad request"

}

6. Implementa HATEOAS (opzionale)

{

"id": 123,

"nome": "Marco",

"_links": {

"self": { "href": "/api/users/123" },

"orders": { "href": "/api/users/123/orders" },

"edit": { "href": "/api/users/123", "method": "PUT" },

"delete": { "href": "/api/users/123", "method": "DELETE" }

}

}

Documentazione API

OpenAPI/Swagger

openapi: 3.0.0

info:

title: User API

version: 1.0.0

paths:

/users:

get:

summary: Lista utenti

responses:

'200':

description: Successo

content:

application/json:

schema:

type: array

items:

$ref: '#/components/schemas/User'

post:

summary: Crea utente

requestBody:

required: true

content:

application/json:

schema:

$ref: '#/components/schemas/NewUser'

responses:

'201':

description: Creato

content:

application/json:

schema:

$ref: '#/components/schemas/User'

components:

schemas:

User:

type: object

properties:

id:

type: integer

nome:

type: string

email:

type: string

NewUser:

type: object

required:

- nome

- email

properties:

nome:

type: string

email:

type: string

Testing API

Jest + Supertest

const request = require('supertest');

const app = require('./app');

describe('User API', () => {

test('GET /api/users - Lista utenti', async () => {

const response = await request(app)

.get('/api/users')

.expect('Content-Type', /json/)

.expect(200);

expect(Array.isArray(response.body)).toBe(true);

});

test('POST /api/users - Crea utente', async () => {

const newUser = {

nome: "Marco",

email: "marco@example.com"

};

const response = await request(app)

.post('/api/users')

.send(newUser)

.expect('Content-Type', /json/)

.expect(201);

expect(response.body).toHaveProperty('id');

expect(response.body.nome).toBe('Marco');

});

test('GET /api/users/999 - Utente non trovato', async () => {

await request(app)

.get('/api/users/999')

.expect(404);

});

});

Conclusione

Le API REST con JSON sono essenziali per:

  • ✅ Comunicazione frontend-backend
  • ✅ Integrazione tra servizi
  • ✅ App mobile
  • ✅ Microservizi
  • ✅ Webhooks

Best practices chiave:
  • Usa metodi HTTP corretti
  • Restituisci codici status appropriati
  • Documenta con OpenAPI
  • Implementa autenticazione
  • Gestisci errori in modo chiaro
  • Versiona l'API

Con queste conoscenze, sei pronto a creare e consumare API REST professionali!

Share:

Articoli Correlati

Read in English