·6 min read
JSON Form Validation: React Hook Form, Formik, and Beyond
JSON is increasingly used to define form structures and validation rules in web applications. By using JSON schemas for form validation, developers can create consistent, maintainable, and type-safe forms across frontend frameworks. This guide covers form validation with JSON Schema, React Hook Form, Formik, Zod, and Yup, with practical examples and best practices. Use our JSON to React Hook Form and JSON to Formik tools to generate validation schemas instantly.
Why Use JSON for Form Validation?
| Approach | Pros | Cons |
|---|---|---|
| JSON Schema | Language-agnostic, reusable, self-documenting | Verbose for simple forms |
| Zod | TypeScript-first, concise syntax, excellent DX | TypeScript-only |
| Yup | Chainable API, good error messages | Larger bundle, slower than Zod |
| React Hook Form | Performant, minimal re-renders | Requires schema resolver |
| Formik | Mature, well-documented | More boilerplate, more re-renders |
Form Validation with JSON Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "User email address"
},
"password": {
"type": "string",
"minLength": 8,
"pattern": "^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).+$",
"description": "Password with uppercase, lowercase, and number"
},
"age": {
"type": "integer",
"minimum": 18,
"maximum": 120
},
"country": {
"type": "string",
"enum": ["US", "CA", "UK", "AU", "Other"]
},
"agreeToTerms": {
"type": "boolean",
"const": true
}
},
"required": ["email", "password", "agreeToTerms"]
}
React Hook Form with Zod Validation
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
email: z.string().email('Invalid email address'),
password: z
.string()
.min(8, 'Password must be at least 8 characters')
.regex(/[A-Z]/, 'Must contain an uppercase letter')
.regex(/[a-z]/, 'Must contain a lowercase letter')
.regex(/d/, 'Must contain a number'),
age: z.number().min(18).max(120).optional(),
country: z.enum(['US', 'CA', 'UK', 'AU', 'Other']),
agreeToTerms: z.literal(true, {
errorMap: () => ({ message: 'You must agree to terms' })
})
});
function RegistrationForm() {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(schema)
});
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<input {...register('email')} placeholder="Email" />
{errors.email && <p>{errors.email.message}</p>}
<input type="password" {...register('password')} placeholder="Password" />
{errors.password && <p>{errors.password.message}</p>}
<button type="submit">Register</button>
</form>
);
}
Formik with Yup Validation
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object({
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string()
.min(8, 'Too short')
.matches(/[A-Z]/, 'Uppercase required')
.matches(/[a-z]/, 'Lowercase required')
.matches(/d/, 'Number required')
.required('Required'),
age: Yup.number().min(18, 'Must be 18+').max(120).nullable()
});
function RegistrationForm() {
return (
<Formik
initialValues={{ email: '', password: '', age: '' }}
validationSchema={validationSchema}
onSubmit={(values) => console.log(values)}
>
<Form>
<Field name="email" type="email" placeholder="Email" />
<ErrorMessage name="email" component="div" />
<Field name="password" type="password" placeholder="Password" />
<ErrorMessage name="password" component="div" />
<button type="submit">Register</button>
</Form>
</Formik>
);
}
Validating Against JSON Schema in the Backend
// Node.js with Ajv
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
const ajv = new Ajv({ allErrors: true });
addFormats(ajv);
const validate = ajv.compile(userSchema);
app.post('/api/users', (req, res) => {
const valid = validate(req.body);
if (!valid) {
return res.status(422).json({
error: 'Validation failed',
details: validate.errors.map(err => ({
path: err.instancePath,
message: err.message,
params: err.params
}))
});
}
// Process valid data
});
Generate Validation Schemas from JSON
Use our tools to generate validation schemas from sample JSON data:
- JSON to React Hook Form — Generate React Hook Form components with validation
- JSON to Formik — Generate Formik forms with Yup validation
- JSON to Zod Schema — Generate Zod schemas from JSON samples
- JSON to Yup Schema — Generate Yup schemas from JSON samples
- JSON Schema Generator — Generate JSON Schema from data
Validation Error Formatting Best Practices
- Display errors inline, next to the relevant field
- Use clear, actionable error messages (not just "Invalid field")
- Validate on blur and on change, not just on submit
- Debounce async validation (e.g., email uniqueness checks)
- Support both client-side and server-side validation with the same schema
- Always validate JSON input server-side, even with client-side validation
Next Steps
Generate validation schemas from your JSON with JSON to React Hook Form, JSON to Formik, JSON to Zod Schema, or JSON Schema Generator.