Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Almost JSON-spec compliant validation of numeric values #119

Merged
merged 1 commit into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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));
}
}
}