Skip to content

Commit

Permalink
Fix hasAdjacentKeywordInEvaluationPath optimisation (#1124)
Browse files Browse the repository at this point in the history
  • Loading branch information
justin-tay authored Oct 30, 2024
1 parent c7b264e commit 8664d3c
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 13 deletions.
15 changes: 2 additions & 13 deletions src/main/java/com/networknt/schema/BaseJsonValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -392,29 +392,18 @@ public String toString() {
*/
protected boolean hasAdjacentKeywordInEvaluationPath(String keyword) {
JsonSchema schema = getEvaluationParentSchema();
boolean checkInstance = false;
boolean anchor = false;
boolean stop = false;
while (schema != null) {
for (JsonValidator validator : schema.getValidators()) {
if (keyword.equals(validator.getKeyword())) {
return true;
}
if (checkInstance) {
if ("properties".equals(validator.getKeyword()) || "items".equals(validator.getKeyword())) {
stop = true;
} else if ("$dynamicAnchor".equals(validator.getKeyword()) || "$recursiveAnchor".equals(validator.getKeyword())) {
anchor = true;
}
}
}
if (stop && !anchor) {
Object element = schema.getEvaluationPath().getElement(-1);
if ("properties".equals(element) || "items".equals(element)) {
// If there is a change in instance location then return false
return false;
}
schema = schema.getEvaluationParentSchema();
checkInstance = true;
anchor = false;
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@
package com.networknt.schema;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;

import com.networknt.schema.SpecVersion.VersionFlag;
import com.networknt.schema.output.OutputUnit;

/**
* UnevaluatedPropertiesValidatorTest.
Expand Down Expand Up @@ -148,4 +152,92 @@ void unevaluatedPropertiesSchema() {
assertEquals("type", assertions.get(0).getType());
assertEquals("$.unevaluatedProperties.type", assertions.get(0).getEvaluationPath().toString());
}

@Test
void ref() {
String schemaData = "{\r\n"
+ " \"definitions\": {\r\n"
+ " \"other\": {\r\n"
+ " \"type\": \"object\",\r\n"
+ " \"properties\": {\r\n"
+ " \"surfboard\": {\r\n"
+ " \"type\": \"string\"\r\n"
+ " }\r\n"
+ " }\r\n"
+ " }\r\n"
+ " },\r\n"
+ " \"allOf\": [\r\n"
+ " {\r\n"
+ " \"$ref\": \"#/definitions/other\"\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"properties\": {\r\n"
+ " \"wheels\": {},\r\n"
+ " \"headlights\": {}\r\n"
+ " }\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"properties\": {\r\n"
+ " \"pontoons\": {}\r\n"
+ " }\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"properties\": {\r\n"
+ " \"wings\": {}\r\n"
+ " }\r\n"
+ " }\r\n"
+ " ],\r\n"
+ " \"unevaluatedProperties\": false\r\n"
+ "}";
String inputData = "{ \"pontoons\": {}, \"wheels\": {}, \"surfboard\": \"2\" }";
JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V201909).getSchema(schemaData);
Set<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON);
assertEquals(0, messages.size());
}

@Test
void nestedRef() {
String schemaData = "{\r\n"
+ " \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\r\n"
+ " \"type\": \"object\",\r\n"
+ " \"allOf\": [ { \"$ref\": \"https://www.example.org/PrimaryDeviceConfiguration.json#PrimaryDeviceConfiguration\" } ],\r\n"
+ " \"properties\": {\r\n"
+ " \"__type\": { \"const\": \"dk.cachet.carp.common.application.devices.Smartphone\" }\r\n"
+ " },\r\n"
+ " \"unevaluatedProperties\": false\r\n"
+ "}";
String primaryDeviceConfiguration = "{\r\n"
+ " \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\r\n"
+ " \"PrimaryDeviceConfiguration\": {\r\n"
+ " \"$anchor\": \"PrimaryDeviceConfiguration\",\r\n"
+ " \"allOf\": [ { \"$ref\": \"DeviceConfiguration.json#DeviceConfiguration\" } ],\r\n"
+ " \"properties\": {\r\n"
+ " \"isPrimaryDevice\": { \"const\": true }\r\n"
+ " },\r\n"
+ " \"required\": [ \"isPrimaryDevice\" ]\r\n"
+ " }\r\n"
+ " }";
String deviceConfiguration = "{\r\n"
+ " \"$schema\": \"https://json-schema.org/draft/2019-09/schema\",\r\n"
+ " \"DeviceConfiguration\": {\r\n"
+ " \"properties\": {\r\n"
+ " \"roleName\": { \"type\": \"string\" }\r\n"
+ " }\r\n"
+ " }\r\n"
+ "}";
Map<String, String> schemas = new HashMap<>();
schemas.put("https://www.example.org/PrimaryDeviceConfiguration.json", primaryDeviceConfiguration);
schemas.put("https://www.example.org/DeviceConfiguration.json", deviceConfiguration);
JsonSchema schema = JsonSchemaFactory
.getInstance(VersionFlag.V201909,
builder -> builder.schemaLoaders(schemaLoaders -> schemaLoaders.schemas(schemas)))
.getSchema(schemaData);
String inputData = "{ \"isPrimaryDevice\": true, \"roleName\": \"hello\" }";
OutputUnit outputUnit = schema.validate(inputData, InputFormat.JSON, OutputFormat.HIERARCHICAL,
executionContext -> {
executionContext.getExecutionConfig().setAnnotationCollectionEnabled(false);
executionContext.getExecutionConfig().setAnnotationCollectionFilter(keyword -> true);
});
assertTrue(outputUnit.isValid());
}
}

0 comments on commit 8664d3c

Please sign in to comment.