Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate JSON schema compliance with Jackson against an external schema file

I would like to use the Jackson library (https://github.com/FasterXML/jackson) to deal with JSON files in Java, which are described by a JSON schema file.

Now, I would like to validate, if a parsed JSON complies with a JSON schema file, which is parsed by itself.

There is a JSON schema module for Jackson (https://github.com/FasterXML/jackson-module-jsonSchema). However, it appears to me that its primary focus is on creating a JSON schema file from within Java.

What is a good way to validate a JSON schema in Java? - preferably using Jackson, but I am also open to other solutions.

like image 386
madison54 Avatar asked Jul 02 '15 08:07

madison54


People also ask

How do you validate a JSON file against a schema?

The simplest way to check if JSON is valid is to load the JSON into a JObject or JArray and then use the IsValid(JToken, JsonSchema) method with the JSON Schema. To get validation error messages, use the IsValid(JToken, JsonSchema, IList<String> ) or Validate(JToken, JsonSchema, ValidationEventHandler) overloads.

What is JSON Schema validation?

JSON Schema validation asserts constraints on the structure of instance data. An instance location that satisfies all asserted constraints is then annotated with any keywords that contain non-assertion information, such as descriptive metadata and usage hints.


2 Answers

1.) Add Dependency pom.xml :-

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

2.) NoSqlEntity is a meta data for entity that can reside in no-sql database.

Initialized NoSqlEntity with schema file.

public static final NoSqlEntity entity = new NoSqlEntity("PAYOUT_ENTITY", "DB_","/schema/payout_entity.json");

public class NoSqlEntity {
private static final Map<String, NoSqlEntity> STORE = new HashMap<>();

private final AtomicLong seq = new AtomicLong(System.currentTimeMillis());
private IdentityGenerator identityGenerator;
private String entity;
private String collectionName;
private String jsonSchema;
private String idColumn = "id";
private String database;


public NoSqlEntity(String entity, String idColumn, String collectionPrefix,      String jsonSchema) {
    this.entity = entity;
    this.idColumn = idColumn;

    this.collectionName = collectionPrefix + "_" + entity;
    this.jsonSchema = jsonSchema;
    STORE.put(entity, this);
}

public NoSqlEntity(String collectionName, String jsonSchema) {
    this.collectionName = collectionName;
    this.jsonSchema = jsonSchema;
}

public static NoSqlEntity valueOf(String entityType) {
    return STORE.get(entityType);
}

public boolean isNotNullSchema() {
    return jsonSchema != null;
}
 ...
 // Other Getter/Setter properties and methods.
}

3.) Sample format of validation schema file of payout_entity.json-

   {
    "properties":{
          "txId":{"type":"string"}

    }
    "required" :["txId","currency"]
  }

4.) JsonSchemaManager - Validate the incoming JSON schema and cache the schema as well.

public class JsonSchemaManager {
private final static Logger LOGGER = LoggerFactory.getLogger(JsonSchemaManager.class);
protected final static String LS = StandardSystemProperty.LINE_SEPARATOR.value();

private final JsonValidator validator = JsonSchemaFactory.byDefault().getValidator();
private final Map<NoSqlEntity, JsonNode> schemaMap = new HashMap<>();

public JsonNode load(NoSqlEntity noSqlEntity) throws IOException {
    final JsonNode schema = JsonLoader.fromURL(this.getClass().getResource(noSqlEntity.getJsonSchema()));
    schemaMap.put(noSqlEntity, schema);
    return schema;
}

public void validateSchema(NoSqlEntity noSqlEntity, JsonNode toBeValidated, Consumer<ProcessingReport> consumer) {
    try {
        JsonNode schema = schemaMap.get(noSqlEntity);
        if (schema == null) {
            schema = load(noSqlEntity);
        }
        final ProcessingReport report = validator.validate(schema, toBeValidated);
        if (!report.isSuccess()) {
            consumer.accept(report);
        }
    } catch (IOException ex) { //NOSONAR
        throw new InvalidRequestException(ex.toString());
    } catch (ProcessingException ex) { //NOSONAR
        throw new InvalidRequestException(ex.toString());
    }
}

 public synchronized boolean synchronizedCheck(NoSqlEntity noSqlEntity, JsonNode toBeValidated, Consumer<Map<String, Object>> messageConsumers) {
    boolean flags = CommonUtils.unchecked(() -> {
        validateSchema(noSqlEntity, toBeValidated, report -> {
            report.forEach(processingMessage -> messageConsumers.accept(JsonConverter.jsonAsMapObject(processingMessage.asJson())));
        });
        return true;
    }, ex -> {
        throw new RuntimeException(ex.toString()); //NOSONAR
    });
    return flags;
}
}

5.) NoSqlRepository which persist meta data into NoSql DB.

@Component
public class NoSqlRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(NoSqlRepository.class);
private final DocumentFormat documentFormat = DocumentFormat.JSON;
private static final String SEPARATOR = ",";

private static final ThreadLocal<MyLocalVariable> THREAD_LOCAL_VARIABLES = ThreadLocal.withInitial(() -> new MyLocalVariable());


static class MyLocalVariable {
    private JsonSchemaManager schemaManager = new JsonSchemaManager();
    private BasicBSONDecoder bsonDecoder = new BasicBSONDecoder();

    public JsonSchemaManager getSchemaManager() {
        return schemaManager;
    }

    public BasicBSONDecoder getBsonDecoder() {
        return bsonDecoder;
    }
}

private void checkSchemaIfAny(NoSqlEntity noSqlEntity, JsonNode entity) {
    if (noSqlEntity.isNotNullSchema()) {
        THREAD_LOCAL_VARIABLES.get().getSchemaManager().check(noSqlEntity, entity);
    }
}

public String saveEntity(NoSqlEntity noSqlEntity, JsonNode entity){
  // Before persisting payload into noSQL, validate payload against schema.
  this.checkSchemaIfAny(noSqlEntity,entity);
}
// Other CURD methods here...
}
like image 177
Ajay Kumar Avatar answered Sep 23 '22 23:09

Ajay Kumar


Just stumbled about https://github.com/leadpony/justify another implementation of a validator for json schema, also more recent draft versions. (7,6,4)

like image 37
Matthias Wiedemann Avatar answered Sep 20 '22 23:09

Matthias Wiedemann