Skip to content

Commit

Permalink
Almost JSON-spec compliant validation of numeric values (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
kosty authored and stevehu committed Mar 14, 2019
1 parent 7b3c7f0 commit 0f0a24e
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 11 deletions.
69 changes: 58 additions & 11 deletions src/main/java/com/networknt/schema/TypeValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ public static boolean isInteger(String str) {
if (str == null || str.equals("")) {
return false;
}

// all code below could be replaced with
//return str.matrch("[-+]?(?:0|[1-9]\\d*)")
int i = 0;
if (str.charAt(0) == '-' || str.charAt(0) == '+') {
if (str.length() == 1) {
Expand All @@ -126,31 +129,75 @@ public static boolean isNumeric(String str) {
if (str == null || str.equals("")) {
return false;
}

// all code below could be replaced with
//return str.matrch("[-+]?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?")
int i = 0;
boolean hasDot = false;
if (str.charAt(0) == '-' || str.charAt(0) == '+') {
int len = str.length();

if (str.charAt(i) == MINUS || str.charAt(i) == PLUS) {
if (str.length() == 1) {
return false;
}
i = 1;
}
for (; i < str.length(); i++) {
char c = str.charAt(i);
if ((c < '0' || c > '9') && c != '.') {

char c = str.charAt(i++);

if (c == CHAR_0) {
// TODO: if leading zeros are supported (counter to JSON spec) handle it here
if (i < len){
c = str.charAt(i++);
if (c != DOT && c != CHAR_E && c != CHAR_e) {
return false;
}
}
} else if (CHAR_1 <= c && c <= CHAR_9) {
while ( i < len && CHAR_0 <= c && c <= CHAR_9 ) {
c = str.charAt(i++);
}
} else {
return false;
}

if (c == DOT) {
if (i >= len) {
return false;
}
c = str.charAt(i++);
while ( i < len && CHAR_0 <= c && c <= CHAR_9 ) {
c = str.charAt(i++);
}
}

if (c == CHAR_E || c == CHAR_e) {
if (i >= len ) {
return false;
}
if (c == '.') {
if (hasDot) {
c = str.charAt(i++);
if (c == PLUS || c == MINUS) {
if (i >= len) {
return false;
}
else {
hasDot = true;
}
c = str.charAt(i++);
}
while ( i < len && CHAR_0 <= c && c <= CHAR_9 ) {
c = str.charAt(i++);
}
}
return true;

return i >= len && (CHAR_0 <= c && c <= CHAR_9);
}

private static final char CHAR_0 = '0';
private static final char CHAR_1 = '1';
private static final char CHAR_9 = '9';
private static final char MINUS = '-';
private static final char PLUS = '+';
private static final char DOT = '.';
private static final char CHAR_E = 'E';
private static final char CHAR_e = 'e';

/**
* Check if the type of the JsonNode's value is number based on the
* status of typeLoose flag.
Expand Down
36 changes: 36 additions & 0 deletions src/test/java/com/networknt/schema/TypeValidatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.networknt.schema;

import org.junit.Test;

import static com.networknt.schema.TypeValidator.isNumeric;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.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(validValue, isNumeric(validValue));
}
}

@Test
public void testNonNumeicValues() {
for(String invalidValue : invalidNumericValues) {
assertFalse(invalidValue, isNumeric(invalidValue));
}
}
}

0 comments on commit 0f0a24e

Please sign in to comment.