Skip to content

Commit

Permalink
Add test for type loose for array and update doc for behavior (#946)
Browse files Browse the repository at this point in the history
  • Loading branch information
justin-tay authored Feb 2, 2024
1 parent c7e7ab4 commit 91385c2
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 53 deletions.
2 changes: 1 addition & 1 deletion doc/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ JsonSchema jsonSchema = JsonSchemaFactory.getInstance().getSchema(schema, config

* typeLoose

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 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.

* strictness
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.
Expand Down
52 changes: 52 additions & 0 deletions src/test/java/com/networknt/schema/StringCheckerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2016 Network New Technologies Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.networknt.schema;

import org.junit.jupiter.api.Test;

import static com.networknt.schema.utils.StringChecker.isNumeric;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class StringCheckerTest {

private static final String[] validNumericValues = {
"1", "-1", "1.1", "-1.1", "0E+1", "0E-1", "0E1", "-0E+1", "-0E-1", "-0E1", "0.1E+1", "0.1E-1", "0.1E1",
"-0.1E+1", "-0.1E-1", "-0.1E1", "10.1", "-10.1", "10E+1", "10E-1", "10E1", "-10E+1", "-10E-1", "-10E1",
"10.1E+1", "10.1E-1", "10.1E1", "-10.1E+1", "-10.1E-1", "-10.1E1", "1E+0", "1E-0", "1E0",
"1E00000000000000000000"
};
private static final String[] invalidNumericValues = {
"01.1", "1.", ".1", "0.1.1", "E1", "E+1", "E-1", ".E1", ".E+1", ".E-1", ".1E1", ".1E+1", ".1E-1", "1E-",
"1E+", "1E", "+", "-", "1a", "0.1a", "0E1a", "0E-1a", "1.0a", "1.0aE1"
//, "+0", "+1" // for backward compatibility, in violation of JSON spec
};

@Test
void testNumericValues() {
for (String validValue : validNumericValues) {
assertTrue(isNumeric(validValue), validValue);
}
}

@Test
void testNonNumericValues() {
for (String invalidValue : invalidNumericValues) {
assertFalse(isNumeric(invalidValue), invalidValue);
}
}
}
147 changes: 95 additions & 52 deletions src/test/java/com/networknt/schema/TypeValidatorTest.java
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,52 +1,95 @@
/*
* Copyright (c) 2016 Network New Technologies Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.networknt.schema;

import org.junit.jupiter.api.Test;

import static com.networknt.schema.utils.StringChecker.isNumeric;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class TypeValidatorTest {

private static final String[] validNumericValues = {
"1", "-1", "1.1", "-1.1", "0E+1", "0E-1", "0E1", "-0E+1", "-0E-1", "-0E1", "0.1E+1", "0.1E-1", "0.1E1",
"-0.1E+1", "-0.1E-1", "-0.1E1", "10.1", "-10.1", "10E+1", "10E-1", "10E1", "-10E+1", "-10E-1", "-10E1",
"10.1E+1", "10.1E-1", "10.1E1", "-10.1E+1", "-10.1E-1", "-10.1E1", "1E+0", "1E-0", "1E0",
"1E00000000000000000000"
};
private static final String[] invalidNumericValues = {
"01.1", "1.", ".1", "0.1.1", "E1", "E+1", "E-1", ".E1", ".E+1", ".E-1", ".1E1", ".1E+1", ".1E-1", "1E-",
"1E+", "1E", "+", "-", "1a", "0.1a", "0E1a", "0E-1a", "1.0a", "1.0aE1"
//, "+0", "+1" // for backward compatibility, in violation of JSON spec
};

@Test
public void testNumeicValues() {
for (String validValue : validNumericValues) {
assertTrue(isNumeric(validValue), validValue);
}
}

@Test
public void testNonNumeicValues() {
for (String invalidValue : invalidNumericValues) {
assertFalse(isNumeric(invalidValue), invalidValue);
}
}
}
/*
* Copyright (c) 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.networknt.schema;

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

import java.util.Set;

import org.junit.jupiter.api.Test;

import com.networknt.schema.SpecVersion.VersionFlag;

/**
* Test TypeValidator validator.
*/
public class TypeValidatorTest {
String schemaData = "{\r\n" // Issue 415
+ " \"$schema\": \"http://json-schema.org/draft-07/schema\",\r\n"
+ " \"$id\": \"http://example.com/example.json\",\r\n"
+ " \"type\": \"object\",\r\n"
+ " \"properties\": {\r\n"
+ " \"array_of_integers\": {\r\n"
+ " \"$id\": \"#/properties/array_of_integers\",\r\n"
+ " \"type\": \"array\",\r\n"
+ " \"items\": {\r\n"
+ " \"type\": \"integer\"\r\n"
+ " }\r\n"
+ " },\r\n"
+ " \"array_of_objects\": {\r\n"
+ " \"$id\": \"#/properties/array_of_objects\",\r\n"
+ " \"type\": \"array\",\r\n"
+ " \"items\": {\r\n"
+ " \"type\": \"object\"\r\n"
+ " }\r\n"
+ " }\r\n"
+ " }\r\n"
+ "}";

@Test
void testTypeLoose() {
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012);
JsonSchema schema = factory.getSchema(schemaData);

String inputData = "{\r\n"
+ " \"array_of_integers\": 1,\r\n"
+ " \"array_of_objects\": {}\r\n"
+ "}";
String validTypeLooseInputData = "{\r\n"
+ " \"array_of_integers\": [\"1\"],\r\n"
+ " \"array_of_objects\": [{}]\r\n"
+ "}";
String invalidTypeLooseData = "{\r\n"
+ " \"array_of_integers\": \"a\",\r\n"
+ " \"array_of_objects\": {}\r\n"
+ "}";
// Without type loose this has 2 type errors
Set<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON);
assertEquals(2, messages.size());
assertEquals(2, messages.stream().filter(m -> "type".equals(m.getType())).count());

// 1 type error in array_of_integers
messages = schema.validate(validTypeLooseInputData, InputFormat.JSON);
assertEquals(1, messages.size());
assertEquals(1, messages.stream().filter(m -> "type".equals(m.getType())).count());

// With type loose this has 0 type errors as any item can also be interpreted as an array of 1 item
SchemaValidatorsConfig config = new SchemaValidatorsConfig();
config.setTypeLoose(true);
JsonSchema typeLoose = factory.getSchema(schemaData, config);
messages = typeLoose.validate(inputData, InputFormat.JSON);
assertEquals(0, messages.size());

// No errors
messages = typeLoose.validate(validTypeLooseInputData, InputFormat.JSON);
assertEquals(0, messages.size());

// Error because a string cannot be interpreted as an array of integer
messages = typeLoose.validate(invalidTypeLooseData, InputFormat.JSON);
assertEquals(1, messages.size());

}
}

0 comments on commit 91385c2

Please sign in to comment.