Validate JSON against Schema in Java
This tutorial shows how to validate JSON against Schema in Java. It presents a utility class – ValidationUtils.java that implements the validation logic. This tutorial uses the open source Jackson 2.x libraries and fge/json-schema-validator libraries hosted on GitHub.
Jackson, as of date, does not provide support for validating JSON data against a JSON schema. Hence, you cannot use Jackson for validation purposes. The fge JSON schema validator implements the missing validation support on top of Jackson. It supports validation against both, JSON schema draft 3 and draft 4 compliant schemas.
The fge/json-schema-validator library provides a JsonSchema class that represents the JSON schema document. This class is not the same as the JsonSchema class provided by Jackson. To start with the validation process, all you need to do is to load your schema document into an instance of JsonSchema class provided by the schema validator. Similarly, load your JSON document that is to be validated, into an instance of JsonNode class provided by Jackson. Now, call the validate() method on the JsonSchema instance and pass in the JsonNode object. The validate() method returns a ProcessingReport instance that represents the result of the validation.
The isSuccess() method on the ProcessingReport object returns the status of the validation. If the validation fails, you can get the reasons for the failure by iterating the ProcessingReport object and retrieving the ProcessingMessage objects. The ProcessingMessage object represents an issue encountered during validation.
Let’s see an example. The schema.json file below shows a sample JSON schema document. The schema describes a product that has id, name and price as the required attributes and an optional array attribute called tags that should contain at least one value, if specified.
schema.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "Product", "description": "A product from Acme's catalog", "type": "object", "properties": { "id": { "description": "The unique identifier for a product", "type": "integer" }, "name": { "description": "Name of the product", "type": "string" }, "price": { "type": "number", "minimum": 0, "exclusiveMinimum": true }, "tags": { "type": "array", "items": { "type": "string" }, "minItems": 1, "uniqueItems": true } }, "required": ["id", "name", "price"] } |
The data.json file below shows a sample JSON data that conforms to the schema presented above.
data.json
1 2 3 4 5 6 7 |
{ "id": 1, "name": "A green door", "price": 12.50, "tags": ["home", "green"] } |
The main method shown below shows the logic to validate JSON using the utility class presented further below in this tutorial. Note that we are loading the schema and the JSON documents from files. The utility class presents methods that can read the documents from in-memory Strings and remote URLs as well.
Main
1 2 3 4 5 6 7 8 9 10 11 12 |
public static void main( String[] args ) throws IOException, ProcessingException { File schemaFile = new File("/Users/XYZ/schema.json"); File jsonFile = new File("/Users/XYZ/data.json"); if (ValidationUtils.isJsonValid(schemaFile, jsonFile)){ System.out.println("Valid!"); }else{ System.out.println("NOT valid!"); } } |
ValidationUtils.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
package com.wilddiary.json; import java.io.File; import java.io.IOException; import java.net.URL; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.fge.jackson.JsonLoader; import com.github.fge.jsonschema.core.exceptions.ProcessingException; import com.github.fge.jsonschema.core.report.ProcessingMessage; import com.github.fge.jsonschema.core.report.ProcessingReport; import com.github.fge.jsonschema.main.JsonSchema; import com.github.fge.jsonschema.main.JsonSchemaFactory; public class ValidationUtils { public static final String JSON_V4_SCHEMA_IDENTIFIER = "http://json-schema.org/draft-04/schema#"; public static final String JSON_SCHEMA_IDENTIFIER_ELEMENT = "$schema"; public static JsonNode getJsonNode(String jsonText) throws IOException { return JsonLoader.fromString(jsonText); } // getJsonNode(text) ends public static JsonNode getJsonNode(File jsonFile) throws IOException { return JsonLoader.fromFile(jsonFile); } // getJsonNode(File) ends public static JsonNode getJsonNode(URL url) throws IOException { return JsonLoader.fromURL(url); } // getJsonNode(URL) ends public static JsonNode getJsonNodeFromResource(String resource) throws IOException { return JsonLoader.fromResource(resource); } // getJsonNode(Resource) ends public static JsonSchema getSchemaNode(String schemaText) throws IOException, ProcessingException { final JsonNode schemaNode = getJsonNode(schemaText); return _getSchemaNode(schemaNode); } // getSchemaNode(text) ends public static JsonSchema getSchemaNode(File schemaFile) throws IOException, ProcessingException { final JsonNode schemaNode = getJsonNode(schemaFile); return _getSchemaNode(schemaNode); } // getSchemaNode(File) ends public static JsonSchema getSchemaNode(URL schemaFile) throws IOException, ProcessingException { final JsonNode schemaNode = getJsonNode(schemaFile); return _getSchemaNode(schemaNode); } // getSchemaNode(URL) ends public static JsonSchema getSchemaNodeFromResource(String resource) throws IOException, ProcessingException { final JsonNode schemaNode = getJsonNodeFromResource(resource); return _getSchemaNode(schemaNode); } // getSchemaNode() ends public static void validateJson(JsonSchema jsonSchemaNode, JsonNode jsonNode) throws ProcessingException { ProcessingReport report = jsonSchemaNode.validate(jsonNode); if (!report.isSuccess()) { for (ProcessingMessage processingMessage : report) { throw new ProcessingException(processingMessage); } } } // validateJson(Node) ends public static boolean isJsonValid(JsonSchema jsonSchemaNode, JsonNode jsonNode) throws ProcessingException { ProcessingReport report = jsonSchemaNode.validate(jsonNode); return report.isSuccess(); } // validateJson(Node) ends public static boolean isJsonValid(String schemaText, String jsonText) throws ProcessingException, IOException { final JsonSchema schemaNode = getSchemaNode(schemaText); final JsonNode jsonNode = getJsonNode(jsonText); return isJsonValid(schemaNode, jsonNode); } // validateJson(Node) ends public static boolean isJsonValid(File schemaFile, File jsonFile) throws ProcessingException, IOException { final JsonSchema schemaNode = getSchemaNode(schemaFile); final JsonNode jsonNode = getJsonNode(jsonFile); return isJsonValid(schemaNode, jsonNode); } // validateJson(Node) ends public static boolean isJsonValid(URL schemaURL, URL jsonURL) throws ProcessingException, IOException { final JsonSchema schemaNode = getSchemaNode(schemaURL); final JsonNode jsonNode = getJsonNode(jsonURL); return isJsonValid(schemaNode, jsonNode); } // validateJson(Node) ends public static void validateJson(String schemaText, String jsonText) throws IOException, ProcessingException{ final JsonSchema schemaNode = getSchemaNode(schemaText); final JsonNode jsonNode = getJsonNode(jsonText); validateJson(schemaNode, jsonNode); } // validateJson(text) ends public static void validateJson(File schemaFile, File jsonFile) throws IOException, ProcessingException{ final JsonSchema schemaNode = getSchemaNode(schemaFile); final JsonNode jsonNode = getJsonNode(jsonFile); validateJson(schemaNode, jsonNode); } // validateJson(File) ends public static void validateJson(URL schemaDocument, URL jsonDocument) throws IOException, ProcessingException{ final JsonSchema schemaNode = getSchemaNode(schemaDocument); final JsonNode jsonNode = getJsonNode(jsonDocument); validateJson(schemaNode, jsonNode); } // validateJson(URL) ends public static void validateJsonResource(String schemaResource, String jsonResource) throws IOException, ProcessingException{ final JsonSchema schemaNode = getSchemaNode(schemaResource); final JsonNode jsonNode = getJsonNodeFromResource(jsonResource); validateJson(schemaNode, jsonNode); } // validateJsonResource() ends private static JsonSchema _getSchemaNode(JsonNode jsonNode) throws ProcessingException { final JsonNode schemaIdentifier = jsonNode.get(JSON_SCHEMA_IDENTIFIER_ELEMENT); if (null == schemaIdentifier){ ((ObjectNode) jsonNode).put(JSON_SCHEMA_IDENTIFIER_ELEMENT, JSON_V4_SCHEMA_IDENTIFIER); } final JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); return factory.getJsonSchema(jsonNode); } // _getSchemaNode() ends } |
Maven Dependencies
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!-- https://mvnrepository.com/artifact/com.github.fge/json-schema-validator --> <dependency> <groupId>com.github.fge</groupId> <artifactId>json-schema-validator</artifactId> <version>2.2.6</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.fge/jackson-coreutils --> <dependency> <groupId>com.github.fge</groupId> <artifactId>jackson-coreutils</artifactId> <version>1.8</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.fge/json-schema-core --> <dependency> <groupId>com.github.fge</groupId> <artifactId>json-schema-core</artifactId> <version>1.2.5</version> </dependency> |
Output
1 2 |
Valid! |
Thanks Drona !
Congrats for your good job Drona!!!
Exception in thread “main” java.lang.NoClassDefFoundError: com.fasterxml.jackson.annotation.JsonMerge
I am getting this error.
Over eclipse, hovering the error, it shows “The method getJsonSchema(JsonNode) from the type JsonSchemaFactory refers to the missing type ProcessingException”
You need to have the following dependencies in the your maven pom.xml. If your is not maven based then you need to download all the jars as needed and add them to the classpath.
Hello im trying to use this to validate api json response vs schema in an automation project but i cant really figure out how i should do it.
I have the schema in a file.json and the response i can store it in JsonObject.
Could you please help with some tips how i should proceed next to validate?
Hi Drona,
I am also getting error in the below lines,
1)ProcessingReport report = jsonSchemaNode.validate(jsonNode);
2)return factory.getJsonSchema(jsonNode);
Can you please help me to solve this. Thanks in advance.