1 package com.networknt.schema; 2 3 import static org.hamcrest.MatcherAssert.assertThat; 4 import static org.junit.jupiter.api.Assertions.assertEquals; 5 import static org.junit.jupiter.api.Assertions.fail; 6 7 import com.fasterxml.jackson.databind.JsonNode; 8 import com.fasterxml.jackson.databind.ObjectMapper; 9 import java.io.IOException; 10 import java.util.Set; 11 import java.util.stream.Collectors; 12 import org.hamcrest.Matchers; 13 import org.junit.jupiter.api.Test; 14 import org.junit.jupiter.params.ParameterizedTest; 15 import org.junit.jupiter.params.provider.ValueSource; 16 17 18 class JsonWalkApplyDefaultsTest { 19 20 /* @AfterEach 21 void cleanup() { 22 CollectorContext.getInstance().reset(); 23 }*/ 24 25 @ParameterizedTest 26 @ValueSource(booleans = { true, false}) testApplyDefaults3(boolean shouldValidateSchema)27 void testApplyDefaults3(boolean shouldValidateSchema) throws IOException { 28 ObjectMapper objectMapper = new ObjectMapper(); 29 JsonNode inputNode = objectMapper.readTree(getClass().getClassLoader().getResourceAsStream("data/walk-data-default.json")); 30 JsonSchema jsonSchema = createSchema(new ApplyDefaultsStrategy(true, true, true)); 31 ValidationResult result = jsonSchema.walk(inputNode, shouldValidateSchema); 32 if (shouldValidateSchema) { 33 assertThat(result.getValidationMessages().stream().map(ValidationMessage::getMessage).collect(Collectors.toList()), 34 Matchers.containsInAnyOrder("$.outer.mixedObject.intValue_missingButError: string found, integer expected", 35 "$.outer.badArray[1]: integer found, string expected", 36 "$.outer.reference.stringValue_missing_with_default_null: null found, string expected")); 37 } else { 38 assertThat(result.getValidationMessages(), Matchers.empty()); 39 } 40 // TODO: In Java 14 use text blocks 41 assertEquals( 42 objectMapper.readTree( 43 "{\"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\"}}}"), 44 inputNode); 45 } 46 47 @Test testApplyDefaults2()48 void testApplyDefaults2() throws IOException { 49 ObjectMapper objectMapper = new ObjectMapper(); 50 JsonNode inputNode = objectMapper.readTree(getClass().getClassLoader().getResourceAsStream("data/walk-data-default.json")); 51 JsonSchema jsonSchema = createSchema(new ApplyDefaultsStrategy(true, true, false)); 52 ValidationResult result = jsonSchema.walk(inputNode, true); 53 assertThat(result.getValidationMessages().stream().map(ValidationMessage::getMessage).collect(Collectors.toList()), 54 Matchers.containsInAnyOrder("$.outer.mixedObject.intValue_missingButError: string found, integer expected", 55 "$.outer.goodArray[1]: null found, string expected", 56 "$.outer.badArray[1]: null found, string expected", 57 "$.outer.reference.stringValue_missing_with_default_null: null found, string expected")); 58 assertEquals( 59 objectMapper.readTree( 60 "{\"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\"}}}"), 61 inputNode); 62 } 63 64 @Test testApplyDefaults1()65 void testApplyDefaults1() throws IOException { 66 ObjectMapper objectMapper = new ObjectMapper(); 67 JsonNode inputNode = objectMapper.readTree(getClass().getClassLoader().getResourceAsStream("data/walk-data-default.json")); 68 JsonSchema jsonSchema = createSchema(new ApplyDefaultsStrategy(true, false, false)); 69 ValidationResult result = jsonSchema.walk(inputNode, true); 70 assertThat(result.getValidationMessages().stream().map(ValidationMessage::getMessage).collect(Collectors.toList()), 71 Matchers.containsInAnyOrder("$.outer.mixedObject.intValue_null: null found, integer expected", 72 "$.outer.mixedObject.intValue_missingButError: string found, integer expected", 73 "$.outer.goodArray[1]: null found, string expected", 74 "$.outer.badArray[1]: null found, string expected", 75 "$.outer.reference.stringValue_missing_with_default_null: null found, string expected")); 76 assertEquals( 77 objectMapper.readTree( 78 "{\"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\"}}}"), 79 inputNode); 80 } 81 82 @ParameterizedTest 83 @ValueSource(strings = { "walkWithEmptyStrategy", "walkWithNoDefaults", "validateWithApplyAllDefaults"} ) testApplyDefaults0(String method)84 void testApplyDefaults0(String method) throws IOException { 85 ObjectMapper objectMapper = new ObjectMapper(); 86 JsonNode inputNode = objectMapper.readTree(getClass().getClassLoader().getResourceAsStream("data/walk-data-default.json")); 87 JsonNode inputNodeOriginal = objectMapper.readTree(getClass().getClassLoader().getResourceAsStream("data/walk-data-default.json")); 88 Set<ValidationMessage> validationMessages; 89 switch (method) { 90 case "walkWithEmptyStrategy": { 91 JsonSchema jsonSchema = createSchema(new ApplyDefaultsStrategy(false, false, false)); 92 validationMessages = jsonSchema.walk(inputNode, true).getValidationMessages(); 93 break; 94 } 95 case "walkWithNoDefaults": { 96 // same empty strategy, but tests for NullPointerException 97 JsonSchema jsonSchema = createSchema(null); 98 validationMessages = jsonSchema.walk(inputNode, true).getValidationMessages(); 99 break; 100 } 101 case "validateWithApplyAllDefaults": { 102 JsonSchema jsonSchema = createSchema(new ApplyDefaultsStrategy(true, true, true)); 103 validationMessages = jsonSchema.validate(inputNode); 104 break; 105 } 106 default: 107 throw new UnsupportedOperationException(); 108 } 109 assertThat(validationMessages.stream().map(ValidationMessage::getMessage).collect(Collectors.toList()), 110 Matchers.containsInAnyOrder("$.outer.mixedObject: required property 'intValue_missing' not found", 111 "$.outer.mixedObject: required property 'intValue_missingButError' not found", 112 "$.outer.mixedObject.intValue_null: null found, integer expected", 113 "$.outer.goodArray[1]: null found, string expected", 114 "$.outer.badArray[1]: null found, string expected", 115 "$.outer.reference: required property 'stringValue_missing' not found")); 116 assertEquals(inputNodeOriginal, inputNode); 117 } 118 119 @Test testIllegalArgumentException()120 void testIllegalArgumentException() { 121 try { 122 new ApplyDefaultsStrategy(false, true, false); 123 fail("expected IllegalArgumentException"); 124 } catch (IllegalArgumentException ignored) { 125 } 126 } 127 createSchema(ApplyDefaultsStrategy applyDefaultsStrategy)128 private JsonSchema createSchema(ApplyDefaultsStrategy applyDefaultsStrategy) { 129 JsonSchemaFactory schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4); 130 SchemaValidatorsConfig schemaValidatorsConfig = new SchemaValidatorsConfig(); 131 schemaValidatorsConfig.setApplyDefaultsStrategy(applyDefaultsStrategy); 132 return schemaFactory.getSchema(getClass().getClassLoader().getResourceAsStream("schema/walk-schema-default.json"), schemaValidatorsConfig); 133 } 134 } 135