Come Validare JSON in Modo Efficace: Guida Completa
Come validare JSON in modo efficace: strumenti, tecniche e best practices. Guida completa per debuggare, formattare e verificare la sintassi JSON oggi.
Perché Validare il JSON
La validazione JSON è essenziale per garantire l'integrità dei dati nelle applicazioni moderne. Un JSON malformato può causare crash, vulnerabilità di sicurezza, e corruzione dati. Questa guida copre tutte le tecniche di validazione, dalla sintassi base alla validazione semantica con JSON Schema, con esempi pratici in diversi linguaggi.
Validazione Sintassi
Errori Comuni
// ❌ Virgola finale (trailing comma)
{
"name": "Mario",
"age": 30, // ← Errore in JSON strict
}
// ❌ Virgolette singole
{
'name': 'Mario' // Deve essere "name": "Mario"
}
// ❌ Commenti (non supportati in JSON)
{
"name": "Mario" // Questo è un errore
}
// ❌ Undefined e funzioni
{
"value": undefined, // Non valido
"func": function() {} // Non valido
}
// ✓ JSON valido
{
"name": "Mario",
"age": 30,
"active": true,
"data": null
}
JavaScript
// Validazione base con try-catch
function isValidJSON(str) {
try {
JSON.parse(str);
return true;
} catch (e) {
return false;
}
}
// Con dettagli errore
function validateJSON(str) {
try {
const data = JSON.parse(str);
return { valid: true, data };
} catch (error) {
return {
valid: false,
error: error.message,
// Posizione errore (approssimativa)
position: error.message.match(/position (\d+)/)?.[1]
};
}
}
// Uso
const result = validateJSON('{"name": "test",}');
// { valid: false, error: "Unexpected token } in JSON at position 17" }
Node.js con Librerie
// json5 - JSON più permissivo (commenti, trailing comma)
const JSON5 = require('json5');
const data = JSON5.parse(`{
// commento permesso
name: 'Mario', // virgolette singole OK
age: 30, // trailing comma OK
}`);
// hjson - Human JSON
const Hjson = require('hjson');
const data = Hjson.parse(`
# commento
name: Mario
age: 30
`);
// jsonlint - Validatore con errori dettagliati
const jsonlint = require('jsonlint');
try {
jsonlint.parse(jsonString);
} catch (e) {
console.log(e.message);
// Error: Parse error on line 3, column 5: ...
}
JSON Schema
Cos'è JSON Schema
JSON Schema è uno standard per descrivere la struttura e le regole di validazione dei dati JSON. Definisce tipi, formati, vincoli e relazioni tra campi.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"description": "Schema per oggetto utente",
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"email": {
"type": "string",
"format": "email"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"role": {
"type": "string",
"enum": ["admin", "user", "guest"]
}
},
"required": ["id", "email", "name"]
}
Tipi e Vincoli
// Tipi base
"type": "string"
"type": "number"
"type": "integer"
"type": "boolean"
"type": "null"
"type": "array"
"type": "object"
// Multipli tipi
"type": ["string", "null"]
// String constraints
{
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[a-z]+$"
}
// Number constraints
{
"type": "number",
"minimum": 0,
"maximum": 100,
"multipleOf": 0.01
}
// Array constraints
{
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
// Object constraints
{
"type": "object",
"properties": { ... },
"required": ["field1", "field2"],
"additionalProperties": false
}
Formati Standard
{
"email": { "format": "email" },
"website": { "format": "uri" },
"birthDate": { "format": "date" },
"createdAt": { "format": "date-time" },
"ip": { "format": "ipv4" },
"uuid": { "format": "uuid" },
"regex": { "format": "regex" }
}
// Nota: format è solo annotazione
// La validazione dipende dalla libreria
Validazione con AJV
// AJV è il validatore JSON Schema più veloce per JavaScript
const Ajv = require('ajv');
const addFormats = require('ajv-formats');
const ajv = new Ajv({ allErrors: true });
addFormats(ajv);
// Schema
const schema = {
type: 'object',
properties: {
email: { type: 'string', format: 'email' },
age: { type: 'integer', minimum: 18 }
},
required: ['email']
};
// Compila schema (una volta)
const validate = ajv.compile(schema);
// Valida dati
const data = { email: 'test@example.com', age: 25 };
const valid = validate(data);
if (!valid) {
console.log(validate.errors);
// [{ instancePath: '/age', message: 'must be >= 18' }]
}
// Errori formattati
const betterAjvErrors = require('better-ajv-errors');
const output = betterAjvErrors(schema, data, validate.errors);
console.log(output);
Validazione con Zod
// Zod: validazione TypeScript-first
import { z } from 'zod';
// Definisci schema
const UserSchema = z.object({
id: z.number().int().positive(),
email: z.string().email(),
name: z.string().min(1).max(100),
age: z.number().int().min(0).max(150).optional(),
role: z.enum(['admin', 'user', 'guest']).default('user'),
tags: z.array(z.string()).min(1).optional()
});
// Tipo TypeScript inferito automaticamente
type User = z.infer;
// Validazione
const result = UserSchema.safeParse({
id: 1,
email: 'mario@example.com',
name: 'Mario Rossi'
});
if (result.success) {
console.log(result.data); // User tipizzato
} else {
console.log(result.error.issues);
// [{ path: ['email'], message: 'Invalid email' }]
}
// Parse con throw
try {
const user = UserSchema.parse(data);
} catch (error) {
if (error instanceof z.ZodError) {
console.log(error.errors);
}
}
Validazione in Python
# jsonschema library
from jsonschema import validate, ValidationError
schema = {
"type": "object",
"properties": {
"email": {"type": "string", "format": "email"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["email"]
}
data = {"email": "test@example.com", "age": 25}
try:
validate(instance=data, schema=schema)
print("Valid!")
except ValidationError as e:
print(f"Error: {e.message}")
# Pydantic (type-safe)
from pydantic import BaseModel, EmailStr, Field
class User(BaseModel):
email: EmailStr
name: str = Field(min_length=1, max_length=100)
age: int = Field(ge=0, le=150, default=None)
try:
user = User(email="test@example.com", name="Mario")
print(user.model_dump_json())
except ValueError as e:
print(e.errors())
Validazione API
Express Middleware
const Ajv = require('ajv');
const ajv = new Ajv();
// Middleware factory
function validateBody(schema) {
const validate = ajv.compile(schema);
return (req, res, next) => {
if (!validate(req.body)) {
return res.status(400).json({
error: 'Validation failed',
details: validate.errors
});
}
next();
};
}
// Schema
const createUserSchema = {
type: 'object',
properties: {
email: { type: 'string', format: 'email' },
password: { type: 'string', minLength: 8 }
},
required: ['email', 'password']
};
// Route con validazione
app.post('/users',
validateBody(createUserSchema),
(req, res) => {
// req.body è validato
createUser(req.body);
}
);
Best Practices
- Valida sempre l'input: Mai fidarsi dei dati esterni
- Usa schema tipizzati: Zod, Pydantic per type safety
- Errori chiari: Restituisci messaggi utili all'utente
- Sanitizza: Rimuovi campi non previsti (additionalProperties: false)
- Compila schema: Compila una volta, valida molte
Strumenti Online
Per validare JSON rapidamente:
- JSON Formatter - Formatta e valida JSON
- JSON Schema Generator - Genera schema da JSON
- Diff Checker - Confronta JSON
Conclusione
La validazione JSON è fondamentale per:
- Sicurezza: Previeni injection e data corruption
- Affidabilità: Cattura errori prima che causino problemi
- DX: Errori chiari aiutano il debug
- Documentazione: Schema descrive l'API
Usa JSON Schema per API e configurazioni, Zod/Pydantic per applicazioni TypeScript/Python.
Per altri strumenti utili, esplora i nostri tool online gratuiti. Per approfondimenti, consulta JSON Schema specification.