Skip to content

Commit

Permalink
Optimize getValueNodeType (#1048)
Browse files Browse the repository at this point in the history
  • Loading branch information
justin-tay authored Jun 6, 2024
1 parent 880329b commit 7728325
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 55 deletions.
18 changes: 15 additions & 3 deletions src/main/java/com/networknt/schema/JsonType.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package com.networknt.schema;

/**
* Indicates the type.
*/
public enum JsonType {
OBJECT("object"),
ARRAY("array"),
Expand All @@ -29,14 +32,23 @@ public enum JsonType {
UNKNOWN("unknown"),
UNION("union");

private String type;
private final String type;

/**
* Constructor.
*
* @param typeStr the type value
*/
private JsonType(String typeStr) {
type = typeStr;
this.type = typeStr;
}

/**
* Gets the type value.
*/
@Override
public String toString() {
return type;
return this.type;
}

}
67 changes: 39 additions & 28 deletions src/main/java/com/networknt/schema/TypeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,18 @@
package com.networknt.schema;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;

/**
* Type factory.
*/
public class TypeFactory {
/**
* Gets the {@link JsonType} indicated by the schema node.
*
* @param node the schema node
* @return the json type
*/
public static JsonType getSchemaNodeType(JsonNode node) {
//Single Type Definition
if (node.isTextual()) {
Expand Down Expand Up @@ -57,37 +67,38 @@ public static JsonType getSchemaNodeType(JsonNode node) {
return JsonType.UNKNOWN;
}

/**
* Gets the {@link JsonType} of the value node.
*
* @param node the value node
* @param config the config
* @return the json type
*/
public static JsonType getValueNodeType(JsonNode node, SchemaValidatorsConfig config) {
if (node.isContainerNode()) {
if (node.isObject())
return JsonType.OBJECT;
if (node.isArray())
return JsonType.ARRAY;
return JsonType.UNKNOWN;
}

if (node.isValueNode()) {
if (node.isTextual())
return JsonType.STRING;
if (node.isBinary())
return JsonType.STRING;
if (node.isIntegralNumber())
JsonNodeType type = node.getNodeType();
switch (type) {
case OBJECT:
return JsonType.OBJECT;
case ARRAY:
return JsonType.ARRAY;
case STRING:
case BINARY:
return JsonType.STRING;
case NUMBER:
if (node.isIntegralNumber()) {
return JsonType.INTEGER;
if (node.isNumber())
if (config != null && config.isJavaSemantics() && node.canConvertToExactIntegral())
return JsonType.INTEGER;
else if (config != null && config.isLosslessNarrowing() && node.canConvertToExactIntegral())
return JsonType.INTEGER;
else
return JsonType.NUMBER;
if (node.isBoolean())
return JsonType.BOOLEAN;
if (node.isNull())
return JsonType.NULL;
} else if (config != null && (config.isJavaSemantics() || config.isLosslessNarrowing())
&& node.canConvertToExactIntegral()) {
return JsonType.INTEGER;
} else {
return JsonType.NUMBER;
}
case BOOLEAN:
return JsonType.BOOLEAN;
case NULL:
return JsonType.NULL;
default:
return JsonType.UNKNOWN;
}

return JsonType.UNKNOWN;
}

}
147 changes: 123 additions & 24 deletions src/test/java/com/networknt/schema/TypeFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,35 @@

package com.networknt.schema;

import com.fasterxml.jackson.databind.node.DecimalNode;
import org.junit.jupiter.api.Test;
import static com.networknt.schema.TypeFactory.getSchemaNodeType;
import static com.networknt.schema.TypeFactory.getValueNodeType;
import static org.junit.jupiter.api.Assertions.assertSame;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;

import static com.networknt.schema.TypeFactory.getValueNodeType;
import static org.junit.jupiter.api.Assertions.assertSame;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.databind.node.DecimalNode;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.fasterxml.jackson.databind.node.TextNode;
import com.networknt.schema.serialization.JsonMapperFactory;

/**
* Test for TypeFactory.
*/
public class TypeFactoryTest {

private static final String[] validIntegralValues = {
"1", "-1", "0E+1", "0E1", "-0E+1", "-0E1", "10.1E+1", "10.1E1", "-10.1E+1", "-10.1E1", "1E+0", "1E-0",
"1E0", "1E18", "9223372036854775807", "-9223372036854775808", "1.0", "1.00", "-1.0", "-1.00"
};
private static final String[] validIntegralValues = { "1", "-1", "0E+1", "0E1", "-0E+1", "-0E1", "10.1E+1",
"10.1E1", "-10.1E+1", "-10.1E1", "1E+0", "1E-0", "1E0", "1E18", "9223372036854775807",
"-9223372036854775808", "1.0", "1.00", "-1.0", "-1.00" };

private static final String[] validNonIntegralNumberValues = {
"1.1", "-1.1", "1.10"
};
private static final String[] validNonIntegralNumberValues = { "1.1", "-1.1", "1.10" };

private final SchemaValidatorsConfig schemaValidatorsConfig = new SchemaValidatorsConfig();

@Test
public void testIntegralValuesWithJavaSemantics() {
void testIntegralValuesWithJavaSemantics() {
schemaValidatorsConfig.setJavaSemantics(true);
for (String validValue : validIntegralValues) {
assertSame(JsonType.INTEGER,
Expand All @@ -53,7 +59,7 @@ public void testIntegralValuesWithJavaSemantics() {
}

@Test
public void testIntegralValuesWithoutJavaSemantics() {
void testIntegralValuesWithoutJavaSemantics() {
schemaValidatorsConfig.setJavaSemantics(false);
for (String validValue : validIntegralValues) {
assertSame(JsonType.NUMBER,
Expand All @@ -67,33 +73,126 @@ public void testIntegralValuesWithoutJavaSemantics() {
}
}


@Test
public void testWithLosslessNarrowing() {
void testWithLosslessNarrowing() {
schemaValidatorsConfig.setLosslessNarrowing(true);
for (String validValue : validIntegralValues) {
assertSame(JsonType.INTEGER,
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.0")), schemaValidatorsConfig),
validValue);
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.0")), schemaValidatorsConfig), validValue);

assertSame(JsonType.NUMBER,
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.5")), schemaValidatorsConfig),
validValue);
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.5")), schemaValidatorsConfig), validValue);
}
}

@Test
public void testWithoutLosslessNarrowing() {
void testWithoutLosslessNarrowing() {
schemaValidatorsConfig.setLosslessNarrowing(false);
for (String validValue : validIntegralValues) {
assertSame(JsonType.NUMBER,
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.0")), schemaValidatorsConfig),
validValue);
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.0")), schemaValidatorsConfig), validValue);

assertSame(JsonType.NUMBER,
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.5")), schemaValidatorsConfig),
validValue);
getValueNodeType(DecimalNode.valueOf(new BigDecimal("1.5")), schemaValidatorsConfig), validValue);
}

}

@Test
void testObjectValue() {
assertSame(JsonType.OBJECT, getValueNodeType(JsonMapperFactory.getInstance().getNodeFactory().objectNode(),
schemaValidatorsConfig));
}

@Test
void testArrayValue() {
assertSame(JsonType.ARRAY,
getValueNodeType(JsonMapperFactory.getInstance().getNodeFactory().arrayNode(), schemaValidatorsConfig));
}

@Test
void testBooleanValue() {
assertSame(JsonType.BOOLEAN, getValueNodeType(
JsonMapperFactory.getInstance().getNodeFactory().booleanNode(true), schemaValidatorsConfig));
}

@Test
public void testNullValue() {
assertSame(JsonType.NULL,
getValueNodeType(JsonMapperFactory.getInstance().getNodeFactory().nullNode(), schemaValidatorsConfig));
}

@Test
void testMissingValue() {
assertSame(JsonType.UNKNOWN, getValueNodeType(JsonMapperFactory.getInstance().getNodeFactory().missingNode(),
schemaValidatorsConfig));
}

@Test
void testIntegerValue() {
assertSame(JsonType.INTEGER, getValueNodeType(JsonMapperFactory.getInstance().getNodeFactory().numberNode(10),
schemaValidatorsConfig));
}

@Test
void testBinaryValue() {
assertSame(JsonType.STRING, getValueNodeType(
JsonMapperFactory.getInstance().getNodeFactory().binaryNode("test".getBytes(StandardCharsets.UTF_8)),
schemaValidatorsConfig));
}

@Test
void testUnknownSchema() {
assertSame(JsonType.UNKNOWN, getSchemaNodeType(TextNode.valueOf("unexpected")));
}

@Test
void testMissingSchema() {
assertSame(JsonType.UNKNOWN, getSchemaNodeType(MissingNode.getInstance()));
}

@Test
void testStringSchema() {
assertSame(JsonType.STRING, getSchemaNodeType(TextNode.valueOf(JsonType.STRING.toString())));
}

@Test
void testObjectSchema() {
assertSame(JsonType.OBJECT, getSchemaNodeType(TextNode.valueOf(JsonType.OBJECT.toString())));
}

@Test
void testArraySchema() {
assertSame(JsonType.ARRAY, getSchemaNodeType(TextNode.valueOf(JsonType.ARRAY.toString())));
}

@Test
void testBooleanSchema() {
assertSame(JsonType.BOOLEAN, getSchemaNodeType(TextNode.valueOf(JsonType.BOOLEAN.toString())));
}

@Test
void testNumberSchema() {
assertSame(JsonType.NUMBER, getSchemaNodeType(TextNode.valueOf(JsonType.NUMBER.toString())));
}

@Test
void testIntegerSchema() {
assertSame(JsonType.INTEGER, getSchemaNodeType(TextNode.valueOf(JsonType.INTEGER.toString())));
}

@Test
void testAnySchema() {
assertSame(JsonType.ANY, getSchemaNodeType(TextNode.valueOf(JsonType.ANY.toString())));
}

@Test
void testNullSchema() {
assertSame(JsonType.NULL, getSchemaNodeType(TextNode.valueOf(JsonType.NULL.toString())));
}

@Test
void testUnionSchema() {
assertSame(JsonType.UNION, getSchemaNodeType(JsonMapperFactory.getInstance().getNodeFactory().arrayNode()));
}
}

0 comments on commit 7728325

Please sign in to comment.