Java/Android - Validate String JSON against String schema

svguerin3 picture svguerin3 · Jan 24, 2013 · Viewed 28k times · Source

I am having trouble finding the most simple way to validate a JSON String against a given JSON-schema String (for reference, this is in Java, running in an Android app).

Ideally, I'd like to just pass in a JSON String and a JSON-schema String, and it returns a boolean as to whether it passes the validation. Through searching, I have found the following 2 promising libraries for accomplishing this:

http://jsontools.berlios.de/

https://github.com/fge/json-schema-validator

However, the first one seems fairly outdated with poor support. I implemented the library into my project, and even with their JavaDocs, I was unable to tell how to properly build a "Validator" object for validation.

Similar story with the 2nd one, which seems to be up-to-date with good test code. However, for what I want to do, which is very simple, it seems to be a bit daunting and confusing as to how to specifically accomplish what I want (even after looking at the ValidateServlet.java file).

Curious if anyone has any other suggestions on a good way to accomplish this (from what it seems), simple task that need, or if I perhaps need to stick with the 2nd option from above? Thanks in advance!

Answer

Tihamer picture Tihamer · Mar 7, 2014

A grateful thank you to Douglas Crockford and Francis Galiegue for writing the java-based json schema processor! And the on-line tester at http://json-schema-validator.herokuapp.com/index.jsp is awesome! I really like the helpful error messages (I only found one example in which they failed), though line and column and/or context would be even better (right now, you only get line and column information during JSON format errors (courtesy of Jackson). Finally, I'd like to thank Michael Droettboom for his great tutorial (even if he only covered Python, Ruby, and C while conspicuously ignoring the best language of all :-)).

For those who missed it (like I did at first), there are examples are at github.com/fge/json-schema-processor-examples. While these examples are very impressive, they are not the simple json validation examples that were originally requested (and that I too was looking for). The simple examples are at github.com/fge/json-schema-validator/blob/master/src/main/java/com/github/fge/jsonschema/examples/Example1.java

Alex's code above did not work for me, but was very helpful; my pom is pulling the latest stable release, version 2.0.1 with the following dependency inserted in my maven pom.xml file:

<dependency>
    <groupId>com.github.fge</groupId>
    <artifactId>json-schema-validator</artifactId>
    <version>2.0.1</version>
</dependency>

Then the following java code works fine for me:

import java.io.IOException;
import java.util.Iterator;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jsonschema.exceptions.ProcessingException;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.report.ProcessingMessage;
import com.github.fge.jsonschema.report.ProcessingReport;
import com.github.fge.jsonschema.util.JsonLoader;


public class JsonValidationExample  
{

public boolean validate(String jsonData, String jsonSchema) {
    ProcessingReport report = null;
    boolean result = false;
    try {
        System.out.println("Applying schema: @<@<"+jsonSchema+">@>@ to data: #<#<"+jsonData+">#>#");
        JsonNode schemaNode = JsonLoader.fromString(jsonSchema);
        JsonNode data = JsonLoader.fromString(jsonData);         
        JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); 
        JsonSchema schema = factory.getJsonSchema(schemaNode);
        report = schema.validate(data);
    } catch (JsonParseException jpex) {
        System.out.println("Error. Something went wrong trying to parse json data: #<#<"+jsonData+
                ">#># or json schema: @<@<"+jsonSchema+">@>@. Are the double quotes included? "+jpex.getMessage());
        //jpex.printStackTrace();
    } catch (ProcessingException pex) {  
        System.out.println("Error. Something went wrong trying to process json data: #<#<"+jsonData+
                ">#># with json schema: @<@<"+jsonSchema+">@>@ "+pex.getMessage());
        //pex.printStackTrace();
    } catch (IOException e) {
        System.out.println("Error. Something went wrong trying to read json data: #<#<"+jsonData+
                ">#># or json schema: @<@<"+jsonSchema+">@>@");
        //e.printStackTrace();
    }
    if (report != null) {
        Iterator<ProcessingMessage> iter = report.iterator();
        while (iter.hasNext()) {
            ProcessingMessage pm = iter.next();
            System.out.println("Processing Message: "+pm.getMessage());
        }
        result = report.isSuccess();
    }
    System.out.println(" Result=" +result);
    return result;
}

public static void main(String[] args)
{
    System.out.println( "Starting Json Validation." );
    JsonValidationExample app = new JsonValidationExample();
    String jsonData = "\"Redemption\"";
    String jsonSchema = "{ \"type\": \"string\", \"minLength\": 2, \"maxLength\": 11}";
    app.validate(jsonData, jsonSchema);
    jsonData = "Agony";  // Quotes not included
    app.validate(jsonData, jsonSchema);
    jsonData = "42";
    app.validate(jsonData, jsonSchema);
    jsonData = "\"A\"";
    app.validate(jsonData, jsonSchema);
    jsonData = "\"The pity of Bilbo may rule the fate of many.\"";
    app.validate(jsonData, jsonSchema);
}

}

My result from the above code is:

Starting Json Validation.
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<"Redemption">#>#
 Result=true
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<Agony>#>#
Error. Something went wrong trying to parse json data: #<#<Agony>#># or json schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@. Are the double quotes included?
 Result=false
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<42>#>#
Processing Message: instance type does not match any allowed primitive type
 Result=false
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<"A">#>#
Processing Message: string is too short
 Result=false
Applying schema: @<@<{ "type": "string", "minLength": 2, "maxLength": 11}>@>@ to data: #<#<"The pity of Bilbo may rule the fate of many.">#>#
Processing Message: string is too long
 Result=false

Enjoy!