package com.jetdrone.vertx.yoke.json; import io.vertx.core.json.JsonObject; import java.util.List; import java.util.Map; import java.util.regex.Pattern; public final class ObjectValidator { public static boolean isValid(Object instance, JsonSchemaResolver.Schema schema) { if (!isObject(instance)) { return false; } // apply default value if (instance == null) { instance = schema.get("default"); } // from now on work with maps if (instance instanceof JsonObject) { instance = ((JsonObject) instance).getMap(); } final Map object = (Map) instance; // required takes precedence if instance is null final List<String> required = schema.get("required"); if (object == null && required != null && required.size() > 0) { return false; } if (object != null) { // validate maxProperties Integer maxProperties = schema.get("maxProperties"); if (maxProperties != null) { if (object.keySet().size() > maxProperties) { return false; } } // validate minProperties Integer minProperties = schema.get("minProperties"); if (minProperties != null) { if (object.keySet().size() < minProperties) { return false; } } // validate required if (required != null) { for (String field : required) { if (!object.containsKey(field)) { return false; } } } // TODO: validate additionalProperties // validate dependencies Map<String, Object> dependencies = schema.get("dependencies"); if (dependencies != null) { for (Map.Entry<String, Object> entry : dependencies.entrySet()) { if (object.containsKey(entry.getKey())) { if (entry.getValue() instanceof List) { List<String> propertyDependencies = (List<String>) entry.getValue(); for (String propertyDependency : propertyDependencies) { if (!object.containsKey(propertyDependency)) { return false; } } } if (entry.getValue() instanceof Map) { JsonSchemaResolver.Schema schemaDependency = JsonSchemaResolver.resolveSchema((Map<String, Object>) entry.getValue(), schema.getParent()); if (!JsonSchema.conformsSchema(object.get(entry.getKey()), schemaDependency)) { return false; } } } } } // validate properties final Map<String, Object> properties = schema.get("properties"); if (properties != null) { for (Map.Entry<String, Object> entry : properties.entrySet()) { String name = entry.getKey(); Object property = entry.getValue(); JsonSchemaResolver.Schema propertySchema = null; if (property instanceof JsonSchemaResolver.Schema) { propertySchema = (JsonSchemaResolver.Schema) property; } else { if (property instanceof Map) { // convert to schema propertySchema = JsonSchemaResolver.resolveSchema((Map<String, Object>) property, schema); entry.setValue(propertySchema); } } Object item = object.get(name); // setParentIfNotNull(propertySchema, schema); if (!JsonSchema.conformsSchema(item, propertySchema)) { return false; } } } // validate patternProperties final Map<String, Object> patternProperties = schema.get("patternProperties"); if (patternProperties != null) { for (Map.Entry<String, Object> entry : patternProperties.entrySet()) { String name = entry.getKey(); Pattern pattern = Pattern.compile(name); Object property = entry.getValue(); JsonSchemaResolver.Schema propertySchema = null; if (property instanceof JsonSchemaResolver.Schema) { propertySchema = (JsonSchemaResolver.Schema) property; } else { if (property instanceof Map) { // convert to schema propertySchema = JsonSchemaResolver.resolveSchema((Map<String, Object>) property); entry.setValue(propertySchema); } } for (Object key : object.keySet()) { if(pattern.matcher((String) key).matches()) { Object item = object.get(key); // setParentIfNotNull(propertySchema, schema); if (!JsonSchema.conformsSchema(item, propertySchema)) { return false; } } } } } } return true; } private static boolean isObject(Object value) { return value == null || value instanceof Map || value instanceof JsonObject; } }