Skip to content

Commit a2ca992

Browse files
harishvashisthaVashist
andauthored
Setting default value even if that value is null (#555)
* removed unnecessary check * should always set default value even if default=null * test case added which sets value as null when default=null specified in schema * improved apply property default logic to accomodate applyPropertyDefaultsIfNull * updating as per review comment by modifing code structure * removed unnecessary test case data * removed unnecessary schema cases * review comment fixed to set nullnode even if nullNode is present in array * apply default null even if null is provided in data when shouldApplyPropertyDefaultsIfNull is true Co-authored-by: Vashist <[email protected]>
1 parent 08ec68e commit a2ca992

File tree

5 files changed

+34
-19
lines changed

5 files changed

+34
-19
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<modelVersion>4.0.0</modelVersion>
2121
<groupId>com.networknt</groupId>
2222
<artifactId>json-schema-validator</artifactId>
23-
<version>1.0.68</version>
23+
<version>1.0.68-SNAPSHOT2</version>
2424
<packaging>bundle</packaging>
2525
<description>A json schema validator that supports draft v4, v6, v7 and v2019-09</description>
2626
<url>https://github.com/networknt/json-schema-validator</url>

src/main/java/com/networknt/schema/ItemsValidator.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at,
123123
JsonNode defaultNode = null;
124124
if (applyDefaultsStrategy.shouldApplyArrayDefaults() && schema != null) {
125125
defaultNode = schema.getSchemaNode().get("default");
126-
if (defaultNode != null && defaultNode.isNull()) {
127-
defaultNode = null;
128-
}
129126
}
130127
int i = 0;
131128
for (JsonNode n : arrayNode) {

src/main/java/com/networknt/schema/PropertiesValidator.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,17 +132,23 @@ private void applyPropertyDefaults(ObjectNode node) {
132132
for (Map.Entry<String, JsonSchema> entry : schemas.entrySet()) {
133133
JsonNode propertyNode = node.get(entry.getKey());
134134

135-
if (propertyNode == null || (applyDefaultsStrategy.shouldApplyPropertyDefaultsIfNull() && propertyNode.isNull())) {
136-
JsonSchema propertySchema = entry.getValue();
137-
JsonNode defaultNode = propertySchema.getSchemaNode().get("default");
138-
if (defaultNode != null && !defaultNode.isNull()) {
139-
// mutate the input json
140-
node.set(entry.getKey(), defaultNode);
141-
}
135+
JsonNode defaultNode = getDefaultNode(entry);
136+
if (defaultNode == null) {
137+
continue;
138+
}
139+
boolean applyDefault = propertyNode == null
140+
|| (propertyNode.isNull() && applyDefaultsStrategy.shouldApplyPropertyDefaultsIfNull());
141+
if (applyDefault) {
142+
node.set(entry.getKey(), defaultNode);
142143
}
143144
}
144145
}
145146

147+
private JsonNode getDefaultNode(final Map.Entry<String, JsonSchema> entry) {
148+
JsonSchema propertySchema = entry.getValue();
149+
return propertySchema.getSchemaNode().get("default");
150+
}
151+
146152
private void walkSchema(Map.Entry<String, JsonSchema> entry, JsonNode node, JsonNode rootNode, String at,
147153
boolean shouldValidateSchema, Set<ValidationMessage> validationMessages, WalkListenerRunner propertyWalkListenerRunner) {
148154
JsonSchema propertySchema = entry.getValue();

src/test/java/com/networknt/schema/JsonWalkApplyDefaultsTest.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818

1919
class JsonWalkApplyDefaultsTest {
2020

21-
@AfterEach
21+
/* @AfterEach
2222
void cleanup() {
2323
CollectorContext.getInstance().reset();
24-
}
24+
}*/
2525

2626
@ParameterizedTest
2727
@ValueSource(booleans = { true, false})
@@ -33,14 +33,15 @@ void testApplyDefaults3(boolean shouldValidateSchema) throws IOException {
3333
if (shouldValidateSchema) {
3434
assertThat(result.getValidationMessages().stream().map(ValidationMessage::getMessage).collect(Collectors.toList()),
3535
Matchers.containsInAnyOrder("$.outer.mixedObject.intValue_missingButError: string found, integer expected",
36-
"$.outer.badArray[1]: integer found, string expected"));
36+
"$.outer.badArray[1]: integer found, string expected",
37+
"$.outer.reference.stringValue_missing_with_default_null: null found, string expected"));
3738
} else {
3839
assertThat(result.getValidationMessages(), Matchers.empty());
3940
}
4041
// TODO: In Java 14 use text blocks
4142
assertEquals(
4243
objectMapper.readTree(
43-
"{\"outer\":{\"mixedObject\":{\"intValue_present\":8,\"intValue_missing\":15,\"intValue_missing_notRequired\":25,\"intValue_null\":35,\"intValue_missingButError\":\"forty-five\"},\"goodArray\":[\"hello\",\"five\"],\"badArray\":[\"hello\",5],\"reference\":{\"stringValue_missing\":\"hello\"}}}"),
44+
"{\"outer\":{\"mixedObject\":{\"intValue_present\":8,\"intValue_null\":35,\"intValue_missingButError\":\"forty-five\",\"intValue_missing\":15,\"intValue_missing_notRequired\":25},\"goodArray\":[\"hello\",\"five\"],\"badArray\":[\"hello\",5],\"reference\":{\"stringValue_missing_with_default_null\":null,\"stringValue_missing\":\"hello\"}}}"),
4445
inputNode);
4546
}
4647

@@ -53,10 +54,11 @@ void testApplyDefaults2() throws IOException {
5354
assertThat(result.getValidationMessages().stream().map(ValidationMessage::getMessage).collect(Collectors.toList()),
5455
Matchers.containsInAnyOrder("$.outer.mixedObject.intValue_missingButError: string found, integer expected",
5556
"$.outer.goodArray[1]: null found, string expected",
56-
"$.outer.badArray[1]: null found, string expected"));
57+
"$.outer.badArray[1]: null found, string expected",
58+
"$.outer.reference.stringValue_missing_with_default_null: null found, string expected"));
5759
assertEquals(
5860
objectMapper.readTree(
59-
"{\"outer\":{\"mixedObject\":{\"intValue_present\":8,\"intValue_missing\":15,\"intValue_missing_notRequired\":25,\"intValue_null\":35,\"intValue_missingButError\":\"forty-five\"},\"goodArray\":[\"hello\",null],\"badArray\":[\"hello\",null],\"reference\":{\"stringValue_missing\":\"hello\"}}}"),
61+
"{\"outer\":{\"mixedObject\":{\"intValue_present\":8,\"intValue_null\":35,\"intValue_missingButError\":\"forty-five\",\"intValue_missing\":15,\"intValue_missing_notRequired\":25},\"goodArray\":[\"hello\",null],\"badArray\":[\"hello\",null],\"reference\":{\"stringValue_missing_with_default_null\":null,\"stringValue_missing\":\"hello\"}}}"),
6062
inputNode);
6163
}
6264

@@ -70,10 +72,11 @@ void testApplyDefaults1() throws IOException {
7072
Matchers.containsInAnyOrder("$.outer.mixedObject.intValue_null: null found, integer expected",
7173
"$.outer.mixedObject.intValue_missingButError: string found, integer expected",
7274
"$.outer.goodArray[1]: null found, string expected",
73-
"$.outer.badArray[1]: null found, string expected"));
75+
"$.outer.badArray[1]: null found, string expected",
76+
"$.outer.reference.stringValue_missing_with_default_null: null found, string expected"));
7477
assertEquals(
7578
objectMapper.readTree(
76-
"{\"outer\":{\"mixedObject\":{\"intValue_present\":8,\"intValue_missing\":15,\"intValue_missing_notRequired\":25,\"intValue_null\":null,\"intValue_missingButError\":\"forty-five\"},\"goodArray\":[\"hello\",null],\"badArray\":[\"hello\",null],\"reference\":{\"stringValue_missing\":\"hello\"}}}"),
79+
"{\"outer\":{\"mixedObject\":{\"intValue_present\":8,\"intValue_null\":null,\"intValue_missingButError\":\"forty-five\",\"intValue_missing\":15,\"intValue_missing_notRequired\":25},\"goodArray\":[\"hello\",null],\"badArray\":[\"hello\",null],\"reference\":{\"stringValue_missing_with_default_null\":null,\"stringValue_missing\":\"hello\"}}}"),
7780
inputNode);
7881
}
7982

src/test/resources/schema/walk-schema-default.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
"description": "the test data does not have this attribute, so default should be applied if the ApplyDefaultsStrategy requires it",
1111
"type": "string",
1212
"default": "hello"
13+
},
14+
"stringValue_missing_with_default_null": {
15+
"description": "the test data does not have this attribute, so default as null should be applied if the ApplyDefaultsStrategy requires it",
16+
"type": "string",
17+
"default": null
18+
},
19+
"stringValue_missing_with_no_default": {
20+
"description": "the test data does not have this attribute, no default value should be applied",
21+
"type": "string"
1322
}
1423
},
1524
"required": [

0 commit comments

Comments
 (0)