Java/Android - Validate String JSON against String schema

后端 未结 3 1405
谎友^
谎友^ 2020-12-13 07:54

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).

相关标签:
3条回答
  • 2020-12-13 08:25

    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!

    0 讨论(0)
  • 2020-12-13 08:28

    @Alex's answer worked for me on Android but required me to Multi-dex and add:

        packagingOptions {
            pickFirst 'META-INF/ASL-2.0.txt'
            pickFirst 'draftv4/schema'
            pickFirst 'draftv3/schema'
            pickFirst 'META-INF/LICENSE'
            pickFirst 'META-INF/LGPL-3.0.txt'
        }
    

    to my build.gradle

    0 讨论(0)
  • 2020-12-13 08:41

    This is essentially what the Servlet you linked to does, so it may not be a one-liner but it still is expressive.

    useV4 and useId as specified on the servlet, are for specifying validations option for Default to draft v4 and Use id for addressing.

    You can see it online: http://json-schema-validator.herokuapp.com/

    public boolean validate(String jsonData, String jsonSchema, boolean useV4, boolean useId) throws Exception {
       // create the Json nodes for schema and data
       JsonNode schemaNode = JsonLoader.fromString(jsonSchema); // throws JsonProcessingException if error
       JsonNode data = JsonLoader.fromString(jsonData);         // same here
    
       JsonSchemaFactory factory = JsonSchemaFactories.withOptions(useV4, useId);
       // load the schema and validate
       JsonSchema schema = factory.fromSchema(schemaNode);
       ValidationReport report = schema.validate(data);
    
       return report.isSuccess();
    }
    
    0 讨论(0)
提交回复
热议问题