Skip to content

Commit 91385c2

Browse files
authored
Add test for type loose for array and update doc for behavior (#946)
1 parent c7e7ab4 commit 91385c2

File tree

3 files changed

+148
-53
lines changed

3 files changed

+148
-53
lines changed

doc/config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ JsonSchema jsonSchema = JsonSchemaFactory.getInstance().getSchema(schema, config
2222

2323
* typeLoose
2424

25-
When typeLoose is true, the validator will convert strings to different types to match the type defined in the schema. This is mostly used to validate the JSON request or response for headers, query parameters, path parameters, and cookies. For the HTTP protocol, these are all strings and might be defined as other types in the schema. For example, the page number might be an integer in the schema but passed as a query parameter in string.
25+
When typeLoose is true, the validator will convert strings to different types to match the type defined in the schema. This is mostly used to validate the JSON request or response for headers, query parameters, path parameters, and cookies. For the HTTP protocol, these are all strings and might be defined as other types in the schema. For example, the page number might be an integer in the schema but passed as a query parameter in string. When it comes to validating arrays note that any item can also be interpreted as a size 1 array of that item so the item will be validated against the type defined for the array.
2626

2727
* strictness
2828
This is a map of keywords to whether the keyword's validators should perform a strict or permissive analysis. When strict is true, validators will perform strict checking against the schema.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2016 Network New Technologies Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.networknt.schema;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import static com.networknt.schema.utils.StringChecker.isNumeric;
22+
import static org.junit.jupiter.api.Assertions.assertFalse;
23+
import static org.junit.jupiter.api.Assertions.assertTrue;
24+
25+
public class StringCheckerTest {
26+
27+
private static final String[] validNumericValues = {
28+
"1", "-1", "1.1", "-1.1", "0E+1", "0E-1", "0E1", "-0E+1", "-0E-1", "-0E1", "0.1E+1", "0.1E-1", "0.1E1",
29+
"-0.1E+1", "-0.1E-1", "-0.1E1", "10.1", "-10.1", "10E+1", "10E-1", "10E1", "-10E+1", "-10E-1", "-10E1",
30+
"10.1E+1", "10.1E-1", "10.1E1", "-10.1E+1", "-10.1E-1", "-10.1E1", "1E+0", "1E-0", "1E0",
31+
"1E00000000000000000000"
32+
};
33+
private static final String[] invalidNumericValues = {
34+
"01.1", "1.", ".1", "0.1.1", "E1", "E+1", "E-1", ".E1", ".E+1", ".E-1", ".1E1", ".1E+1", ".1E-1", "1E-",
35+
"1E+", "1E", "+", "-", "1a", "0.1a", "0E1a", "0E-1a", "1.0a", "1.0aE1"
36+
//, "+0", "+1" // for backward compatibility, in violation of JSON spec
37+
};
38+
39+
@Test
40+
void testNumericValues() {
41+
for (String validValue : validNumericValues) {
42+
assertTrue(isNumeric(validValue), validValue);
43+
}
44+
}
45+
46+
@Test
47+
void testNonNumericValues() {
48+
for (String invalidValue : invalidNumericValues) {
49+
assertFalse(isNumeric(invalidValue), invalidValue);
50+
}
51+
}
52+
}
Lines changed: 95 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,95 @@
1-
/*
2-
* Copyright (c) 2016 Network New Technologies Inc.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
17-
package com.networknt.schema;
18-
19-
import org.junit.jupiter.api.Test;
20-
21-
import static com.networknt.schema.utils.StringChecker.isNumeric;
22-
import static org.junit.jupiter.api.Assertions.assertFalse;
23-
import static org.junit.jupiter.api.Assertions.assertTrue;
24-
25-
public class TypeValidatorTest {
26-
27-
private static final String[] validNumericValues = {
28-
"1", "-1", "1.1", "-1.1", "0E+1", "0E-1", "0E1", "-0E+1", "-0E-1", "-0E1", "0.1E+1", "0.1E-1", "0.1E1",
29-
"-0.1E+1", "-0.1E-1", "-0.1E1", "10.1", "-10.1", "10E+1", "10E-1", "10E1", "-10E+1", "-10E-1", "-10E1",
30-
"10.1E+1", "10.1E-1", "10.1E1", "-10.1E+1", "-10.1E-1", "-10.1E1", "1E+0", "1E-0", "1E0",
31-
"1E00000000000000000000"
32-
};
33-
private static final String[] invalidNumericValues = {
34-
"01.1", "1.", ".1", "0.1.1", "E1", "E+1", "E-1", ".E1", ".E+1", ".E-1", ".1E1", ".1E+1", ".1E-1", "1E-",
35-
"1E+", "1E", "+", "-", "1a", "0.1a", "0E1a", "0E-1a", "1.0a", "1.0aE1"
36-
//, "+0", "+1" // for backward compatibility, in violation of JSON spec
37-
};
38-
39-
@Test
40-
public void testNumeicValues() {
41-
for (String validValue : validNumericValues) {
42-
assertTrue(isNumeric(validValue), validValue);
43-
}
44-
}
45-
46-
@Test
47-
public void testNonNumeicValues() {
48-
for (String invalidValue : invalidNumericValues) {
49-
assertFalse(isNumeric(invalidValue), invalidValue);
50-
}
51-
}
52-
}
1+
/*
2+
* Copyright (c) 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.networknt.schema;
17+
18+
import static org.junit.jupiter.api.Assertions.assertEquals;
19+
20+
import java.util.Set;
21+
22+
import org.junit.jupiter.api.Test;
23+
24+
import com.networknt.schema.SpecVersion.VersionFlag;
25+
26+
/**
27+
* Test TypeValidator validator.
28+
*/
29+
public class TypeValidatorTest {
30+
String schemaData = "{\r\n" // Issue 415
31+
+ " \"$schema\": \"http://json-schema.org/draft-07/schema\",\r\n"
32+
+ " \"$id\": \"http://example.com/example.json\",\r\n"
33+
+ " \"type\": \"object\",\r\n"
34+
+ " \"properties\": {\r\n"
35+
+ " \"array_of_integers\": {\r\n"
36+
+ " \"$id\": \"#/properties/array_of_integers\",\r\n"
37+
+ " \"type\": \"array\",\r\n"
38+
+ " \"items\": {\r\n"
39+
+ " \"type\": \"integer\"\r\n"
40+
+ " }\r\n"
41+
+ " },\r\n"
42+
+ " \"array_of_objects\": {\r\n"
43+
+ " \"$id\": \"#/properties/array_of_objects\",\r\n"
44+
+ " \"type\": \"array\",\r\n"
45+
+ " \"items\": {\r\n"
46+
+ " \"type\": \"object\"\r\n"
47+
+ " }\r\n"
48+
+ " }\r\n"
49+
+ " }\r\n"
50+
+ "}";
51+
52+
@Test
53+
void testTypeLoose() {
54+
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012);
55+
JsonSchema schema = factory.getSchema(schemaData);
56+
57+
String inputData = "{\r\n"
58+
+ " \"array_of_integers\": 1,\r\n"
59+
+ " \"array_of_objects\": {}\r\n"
60+
+ "}";
61+
String validTypeLooseInputData = "{\r\n"
62+
+ " \"array_of_integers\": [\"1\"],\r\n"
63+
+ " \"array_of_objects\": [{}]\r\n"
64+
+ "}";
65+
String invalidTypeLooseData = "{\r\n"
66+
+ " \"array_of_integers\": \"a\",\r\n"
67+
+ " \"array_of_objects\": {}\r\n"
68+
+ "}";
69+
// Without type loose this has 2 type errors
70+
Set<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON);
71+
assertEquals(2, messages.size());
72+
assertEquals(2, messages.stream().filter(m -> "type".equals(m.getType())).count());
73+
74+
// 1 type error in array_of_integers
75+
messages = schema.validate(validTypeLooseInputData, InputFormat.JSON);
76+
assertEquals(1, messages.size());
77+
assertEquals(1, messages.stream().filter(m -> "type".equals(m.getType())).count());
78+
79+
// With type loose this has 0 type errors as any item can also be interpreted as an array of 1 item
80+
SchemaValidatorsConfig config = new SchemaValidatorsConfig();
81+
config.setTypeLoose(true);
82+
JsonSchema typeLoose = factory.getSchema(schemaData, config);
83+
messages = typeLoose.validate(inputData, InputFormat.JSON);
84+
assertEquals(0, messages.size());
85+
86+
// No errors
87+
messages = typeLoose.validate(validTypeLooseInputData, InputFormat.JSON);
88+
assertEquals(0, messages.size());
89+
90+
// Error because a string cannot be interpreted as an array of integer
91+
messages = typeLoose.validate(invalidTypeLooseData, InputFormat.JSON);
92+
assertEquals(1, messages.size());
93+
94+
}
95+
}

0 commit comments

Comments
 (0)