Skip to content

Commit f001b36

Browse files
authored
Merge pull request #172 from kosty/issue/171
fixes #171 validation of quoted numerics added
2 parents 6c23a14 + 0a1d65e commit f001b36

File tree

5 files changed

+308
-707
lines changed

5 files changed

+308
-707
lines changed

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

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,26 @@ public MaximumValidator(String schemaPath, final JsonNode schemaNode, JsonSchema
4848

4949
parseErrorCode(getValidatorType().getErrorCodeKey());
5050

51+
final String maximumText = schemaNode.asText();
5152
if (( schemaNode.isLong() || schemaNode.isInt() ) && (JsonType.INTEGER.toString().equals(getNodeFieldType()))) {
5253
// "integer", and within long range
5354
final long lm = schemaNode.asLong();
5455
typedMaximum = new ThresholdMixin() {
5556
@Override
5657
public boolean crossesThreshold(JsonNode node) {
57-
long val = node.asLong();
5858
if (node.isBigInteger()) {
5959
//node.isBigInteger is not trustable, the type BigInteger doesn't mean it is a big number.
60-
if (node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0) {
61-
return true;
62-
}
60+
int compare = node.bigIntegerValue().compareTo(new BigInteger(schemaNode.asText()));
61+
return compare > 0 || (excludeEqual && compare == 0);
62+
63+
} else if (node.isTextual()) {
64+
BigDecimal max = new BigDecimal(maximumText);
65+
BigDecimal value = new BigDecimal(node.asText());
66+
int compare = value.compareTo(max);
67+
return compare > 0 || (excludeEqual && compare == 0);
6368
}
64-
return lm < val || (excludeEqual && lm <= val);
69+
long val = node.asLong();
70+
return lm < val || (excludeEqual && lm == val);
6571
}
6672

6773
@Override
@@ -73,18 +79,27 @@ public String thresholdValue() {
7379
typedMaximum = new ThresholdMixin() {
7480
@Override
7581
public boolean crossesThreshold(JsonNode node) {
76-
if(schemaNode.doubleValue() == Double.POSITIVE_INFINITY) {
82+
if (schemaNode.isDouble() && schemaNode.doubleValue() == Double.POSITIVE_INFINITY) {
83+
return false;
84+
}
85+
if (schemaNode.isDouble() && schemaNode.doubleValue() == Double.NEGATIVE_INFINITY) {
86+
return true;
87+
}
88+
if (node.isDouble() && node.doubleValue() == Double.NEGATIVE_INFINITY) {
7789
return false;
7890
}
79-
final BigDecimal max = new BigDecimal(schemaNode.asText());
80-
if(node.doubleValue() == Double.POSITIVE_INFINITY) {return true;}
91+
if (node.isDouble() && node.doubleValue() == Double.POSITIVE_INFINITY) {
92+
return true;
93+
}
94+
final BigDecimal max = new BigDecimal(maximumText);
8195
BigDecimal value = new BigDecimal(node.asText());
82-
return value.compareTo(max) > 0 || (excludeEqual && value.compareTo(max) == 0);
96+
int compare = value.compareTo(max);
97+
return compare > 0 || (excludeEqual && compare == 0);
8398
}
8499

85100
@Override
86101
public String thresholdValue() {
87-
return schemaNode.asText();
102+
return maximumText;
88103
}
89104
};
90105
}

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

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class MinimumValidator extends BaseJsonValidator implements JsonValidator
2929
private static final Logger logger = LoggerFactory.getLogger(MinimumValidator.class);
3030
private static final String PROPERTY_EXCLUSIVE_MINIMUM = "exclusiveMinimum";
3131

32-
private boolean excluded = false;
32+
private boolean excludeEqual = false;
3333

3434
/**
3535
* In order to limit number of `if` statements in `validate` method, all the
@@ -46,25 +46,32 @@ public MinimumValidator(String schemaPath, JsonNode schemaNode, JsonSchema paren
4646

4747
JsonNode exclusiveMinimumNode = getParentSchema().getSchemaNode().get(PROPERTY_EXCLUSIVE_MINIMUM);
4848
if (exclusiveMinimumNode != null && exclusiveMinimumNode.isBoolean()) {
49-
excluded = exclusiveMinimumNode.booleanValue();
49+
excludeEqual = exclusiveMinimumNode.booleanValue();
5050
}
5151

5252
parseErrorCode(getValidatorType().getErrorCodeKey());
5353

54-
if ( schemaNode.isLong() || schemaNode.isInt() && JsonType.INTEGER.toString().equals(getNodeFieldType())) {
54+
final String minimumText = schemaNode.asText();
55+
if ((schemaNode.isLong() || schemaNode.isInt()) && JsonType.INTEGER.toString().equals(getNodeFieldType())) {
5556
// "integer", and within long range
5657
final long lmin = schemaNode.asLong();
5758
typedMinimum = new ThresholdMixin() {
5859
@Override
5960
public boolean crossesThreshold(JsonNode node) {
60-
long val = node.asLong();
61-
if(node.isBigInteger()) {
61+
if (node.isBigInteger()) {
6262
//node.isBigInteger is not trustable, the type BigInteger doesn't mean it is a big number.
63-
if(node.bigIntegerValue().compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0) {
64-
return true;
65-
}
63+
int compare = node.bigIntegerValue().compareTo(new BigInteger(minimumText));
64+
return compare < 0 || (excludeEqual && compare == 0);
65+
66+
} else if (node.isTextual()) {
67+
BigDecimal min = new BigDecimal(minimumText);
68+
BigDecimal value = new BigDecimal(node.asText());
69+
int compare = value.compareTo(min);
70+
return compare < 0 || (excludeEqual && compare == 0);
71+
6672
}
67-
return lmin > val || (excluded && lmin >= val);
73+
long val = node.asLong();
74+
return lmin > val || (excludeEqual && lmin == val);
6875
}
6976

7077
@Override
@@ -77,18 +84,28 @@ public String thresholdValue() {
7784
typedMinimum = new ThresholdMixin() {
7885
@Override
7986
public boolean crossesThreshold(JsonNode node) {
80-
if(schemaNode.doubleValue() == Double.NEGATIVE_INFINITY) {
87+
// jackson's BIG_DECIMAL parsing is limited. see https://github.com/FasterXML/jackson-databind/issues/1770
88+
if (schemaNode.isDouble() && schemaNode.doubleValue() == Double.NEGATIVE_INFINITY) {
89+
return false;
90+
}
91+
if (schemaNode.isDouble() && schemaNode.doubleValue() == Double.POSITIVE_INFINITY) {
92+
return true;
93+
}
94+
if (node.isDouble() && node.doubleValue() == Double.NEGATIVE_INFINITY) {
95+
return true;
96+
}
97+
if (node.isDouble() && node.doubleValue() == Double.POSITIVE_INFINITY) {
8198
return false;
8299
}
83-
final BigDecimal min = new BigDecimal(schemaNode.asText());
84-
if(node.doubleValue() == Double.NEGATIVE_INFINITY) {return true;}
100+
final BigDecimal min = new BigDecimal(minimumText);
85101
BigDecimal value = new BigDecimal(node.asText());
86-
return value.compareTo(min) < 0 || (excluded && value.compareTo(min) == 0);
102+
int compare = value.compareTo(min);
103+
return compare < 0 || (excludeEqual && compare == 0);
87104
}
88105

89106
@Override
90107
public String thresholdValue() {
91-
return schemaNode.asText();
108+
return minimumText;
92109
}
93110
};
94111
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
package com.networknt.schema;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.node.DecimalNode;
5+
import com.fasterxml.jackson.databind.node.DoubleNode;
6+
import com.fasterxml.jackson.databind.node.TextNode;
37
import org.junit.Ignore;
48
import org.junit.Test;
59

610
import java.lang.annotation.Annotation;
711
import java.lang.reflect.InvocationTargetException;
812
import java.lang.reflect.Method;
13+
import java.math.BigDecimal;
914
import java.util.ArrayList;
1015
import java.util.Arrays;
1116
import java.util.List;
1217
import java.util.stream.Collectors;
18+
19+
import static org.junit.Assert.assertTrue;
20+
1321
@Ignore
1422
public class MaximumValidatorPerfTest {
1523
MaximumValidatorTest test = new MaximumValidatorTest();
1624

1725
@Test
1826
public void testTime() throws InvocationTargetException, IllegalAccessException {
19-
test.setUp();
2027
String[] testMethodsToBeExecuted = {"testMaximumDoubleValue"};
2128
List<Method> testMethods = getTestMethods(testMethodsToBeExecuted);
2229
long start = System.currentTimeMillis();

0 commit comments

Comments
 (0)