1. Why you need JSON validation
Imagine you wrote a User class and expect that you will always receive JSON like this:
{
"id": 42,
"name": "Alice",
"email": "alice@example.com"
}
But then you get this:
{
"id": "forty two",
"name": 123,
"email": null,
"admin": true
}
Or even this:
{
"username": "Alice"
}
At best, Jackson or Gson will throw an exception when trying to deserialize. At worst — they will silently assign default values to fields, and your business logic will start behaving incorrectly. And if this is a config for your service — you can end up with nasty bugs the whole team will be chasing later.
JSON validation is the process of checking that the structure, types, and values in JSON conform to a set of rules (a schema). It’s like passport control for data: if you don’t pass — you don’t board!
2. JSON Schema: what it is and what it looks like
In the JSON world there is an official standard for describing data structures — JSON Schema. It’s a “checklist” for verifying that JSON matches your program’s requirements.
JSON Schema is also JSON, just with special keys: type, properties, required, and so on.
A minimal schema example
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
What’s going on here:
- An object is expected (type: "object").
- The object may have fields "id", "name", "email" (described in properties).
- "id" — must be an integer (type: "integer").
- "name" — must be a string (type: "string").
- "email" — a string that looks like an email (the format key with value "email").
- required lists mandatory fields: "id" and "name".
If the JSON lacks "id" or "name", or their type is wrong — validation will fail.
JSON Schema capabilities at a glance
- Type declaration (type: "string", "integer", "array", "object", "boolean", "null").
- Nested objects and arrays (properties, items).
- Required and optional fields (required).
- String length and numeric range checks (minLength, maximum, etc.).
- Format checks (format: "email", "date", "uri", etc.).
- Enumerations (enum: a list of allowed values).
- Regular expressions for strings (pattern).
- Complex conditions: anyOf, oneOf, allOf (for advanced cases).
3. JSON validation in Java: library overview
Schema-based JSON validation isn’t part of the Java standard library. But there are popular third-party libraries. Here are the best-known ones:
- everit-org/json-schema — simple, free, and popular.
- networknt/json-schema-validator — fast and supports the latest drafts.
- Jackson-module-jsonSchema — an extension for Jackson (but it doesn’t support full validation).
- Justify, Java JSON Tools — others exist, but they are less common.
In this lecture we’ll look at everit-org/json-schema — it’s beginner-friendly, well documented, and doesn’t require jumping through hoops.
Installing everit-org/json-schema
Add the dependency to your pom.xml (Maven):
<dependency>
<groupId>org.everit.json</groupId>
<artifactId>org.everit.json.schema</artifactId>
<version>1.14.2</version>
</dependency>
Or via Gradle:
implementation 'org.everit.json:org.everit.json.schema:1.14.2'
4. Example: schema-based JSON validation (step by step)
Let’s validate JSON in practice. We’ll need the schema, the JSON itself, and a bit of code.
Schema example (user-schema.json):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 2, "maxLength": 30 },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
Valid JSON example (user.json):
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
Invalid JSON example:
{
"id": "one",
"name": "",
"email": "not-an-email"
}
Validation code
import org.everit.json.schema.Schema;
import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.json.JSONException;
import org.json.JSONTokener;
import org.everit.json.schema.ValidationException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class JsonValidationExample {
public static void main(String[] args) throws Exception {
// Load schema from file
String schemaString = new String(Files.readAllBytes(Paths.get("user-schema.json")));
JSONObject rawSchema = new JSONObject(new JSONTokener(schemaString));
Schema schema = SchemaLoader.load(rawSchema);
// Load JSON to validate
String jsonString = new String(Files.readAllBytes(Paths.get("user.json")));
JSONObject json = new JSONObject(new JSONTokener(jsonString));
// Validation
try {
schema.validate(json); // If everything is OK — nothing will happen
System.out.println("JSON is valid!");
} catch (ValidationException e) {
System.out.println("JSON is NOT valid!");
for (String msg : e.getAllMessages()) {
System.out.println("Error: " + msg);
}
}
}
}
Code notes:
- It uses the Schema class and the loader SchemaLoader.load(...).
- The method schema.validate(json) throws an exception if the JSON doesn’t conform to the schema.
- In the catch block you can get all errors via getAllMessages().
How do you integrate this into an application?
Typically the schema is stored as a resource (for example, in the resources folder). You validate the JSON before deserializing it into a Java object. If everything is fine — deserialize and proceed.
5. Handling validation errors
When JSON fails validation, the library throws a ValidationException. Its message contains a list of errors describing what doesn’t match the schema.
Example of error output
For the invalid JSON above, the output will look roughly like this:
JSON is NOT valid!
Error: #: required key [id] not found
Error: #/name: expected minLength: 2, actual: 0
Error: #/email: String [not-an-email] is invalid against requested format [email]
Error: #/id: expected type: Integer, found: String
How to interpret the errors:
- required key [id] not found — a required field is missing.
- expected minLength: 2, actual: 0 — the string is too short.
- String [...] is invalid against requested format [email] — an invalid email.
- expected type: Integer, found: String — type mismatch.
Note! The messages may be in English, but they’re pretty self-explanatory.
How do you show errors to the user?
You can collect errors into a list and return them to the user, for example, via a REST API or a GUI. This makes it easy to understand what exactly is wrong with the input data.
6. Practice: validating an array of objects
Often you need to validate not a single object, but an array:
[
{ "id": 1, "name": "Alice", "email": "alice@example.com" },
{ "id": 2, "name": "Bob" },
{ "id": "what is this?", "name": 123, "email": "not-an-email" }
]
Schema:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 2, "maxLength": 30 },
"email": { "type": "string", "format": "email" }
},
"required": ["id", "name"]
}
}
Validation works the same way; you just pass an array as the JSON. Errors will include the indices of the elements where something is wrong (for example, [#/2/id]).
7. Common mistakes when validating JSON
Mistake #1: Data type mismatch. A string often arrives instead of a number ("id": "123") while the schema expects an integer. Validation will fail. If you don’t control the data source — either adjust the schema or convert the data in advance.
Mistake #2: Missing required fields. If the schema marks a field as required ("required": ["id","name"]) but the JSON doesn’t have it — you’ll get an error. This can be surprising: the frontend forgot to send a field, or the API changed.
Mistake #3: Extra fields in JSON. By default, JSON Schema allows extra fields. If you want a strict schema, don’t forget to add "additionalProperties": false. Without it, JSON may contain any stray fields.
Mistake #4: Wrong schema version or syntax. If you use keys that don’t exist in your schema version or make typos, the validator won’t be able to load the schema. Validate your schema at https://www.jsonschemavalidator.net/ or similar services.
Mistake #5: Poor error handling. If you only catch the first exception and don’t show the details, it will be hard to understand what’s wrong with the JSON. Use getAllMessages() to output all errors.
Mistake #6: Overly strict formats. The "format" checks like "email" or "date" can be rather superficial. If you need strict validation, add additional checks in your code.
GO TO FULL VERSION