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

Adds JsonNodeReader #1065

Merged
merged 5 commits into from
Jun 14, 2024
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,8 @@ Assertions contains the following additional information
| Arguments | The arguments used for generating the message.
| Type | The keyword that generated the message.
| Property | The property name that caused the validation error for example for the `required` keyword. Note that this is not part of the instance location as that points to the instance node.
| Schema Node | The `JsonNode` pointed to by the Schema Location. This is the schema data that caused the input data to fail. It is possible to get the location information by configuring the `JsonSchemaFactory` with the `LocationJsonNodeFactoryFactory` and using `JsonNodes.tokenLocationOf(schemaNode)`.
| Instance Node | The `JsonNode` pointed to by the Instance Location. This is the input data that failed validation. It is possible to get the location information by configuring the `JsonSchemaFactory` with the `LocationJsonNodeFactoryFactory` and using `JsonNodes.tokenLocationOf(instanceNode)`.
| Schema Node | The `JsonNode` pointed to by the Schema Location. This is the schema data that caused the input data to fail. It is possible to get the location information by configuring the `JsonSchemaFactory` with a `JsonNodeReader` that uses the `LocationJsonNodeFactoryFactory` and using `JsonNodes.tokenLocationOf(schemaNode)`.
| Instance Node | The `JsonNode` pointed to by the Instance Location. This is the input data that failed validation. It is possible to get the location information by configuring the `JsonSchemaFactory` with a `JsonNodeReader` that uses the `LocationJsonNodeFactoryFactory` and using `JsonNodes.tokenLocationOf(instanceNode)`.
| Details | Additional details that can be set by custom keyword validator implementations. This is not used by the library.

Annotations contains the following additional information
Expand All @@ -367,7 +367,7 @@ Annotations contains the following additional information

The library can be configured to store line and column information in the `JsonNode` instances for the instance and schema nodes. This will adversely affect performance and is not configured by default.

This is done by configuring a `LocationJsonNodeFactoryFactory` on the `JsonSchemaFactory`. The `JsonLocation` information can then be retrieved using `JsonNodes.tokenLocationOf(jsonNode)`.
This is done by configuring a `JsonNodeReader` that uses the `LocationJsonNodeFactoryFactory`on the `JsonSchemaFactory`. The `JsonLocation` information can then be retrieved using `JsonNodes.tokenLocationOf(jsonNode)`.

```java
String schemaData = "{\r\n"
Expand All @@ -383,7 +383,7 @@ String inputData = "{\r\n"
+ " \"startDate\": \"1\"\r\n"
+ "}";
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012,
builder -> builder.jsonNodeFactoryFactory(LocationJsonNodeFactoryFactory.getInstance()));
builder -> builder.jsonNodeReader(JsonNodeReader.builder().locationAware().build()));
SchemaValidatorsConfig config = new SchemaValidatorsConfig();
config.setPathType(PathType.JSON_POINTER);
JsonSchema schema = factory.getSchema(schemaData, InputFormat.JSON, config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ private static class Holder {
private static DisallowUnknownJsonMetaSchemaFactory INSTANCE = new DisallowUnknownJsonMetaSchemaFactory();
}

/**
* Gets the instance of {@link DisallowUnknownJsonMetaSchemaFactory}.
*
* @return the json meta schema factory
*/
public static DisallowUnknownJsonMetaSchemaFactory getInstance() {
return Holder.INSTANCE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ private static class Holder {
private static DisallowUnknownKeywordFactory INSTANCE = new DisallowUnknownKeywordFactory();
}

/**
* Gets the instance of {@link DisallowUnknownKeywordFactory}.
*
* @return the keyword factory
*/
public static DisallowUnknownKeywordFactory getInstance() {
return Holder.INSTANCE;
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/networknt/schema/JsonSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,7 @@ public ValidationResult walk(ExecutionContext executionContext, JsonNode node, b
/**
* Walk the JSON node.
*
* @param <T> the result type
* @param executionContext the execution context
* @param node the input
* @param outputFormat the output format
Expand Down Expand Up @@ -1053,6 +1054,7 @@ public ValidationResult walk(ExecutionContext executionContext, JsonNode node, b
/**
* Walk the JSON node.
*
* @param <T> the result type
* @param executionContext the execution context
* @param node the input
* @param outputFormat the output format
Expand Down Expand Up @@ -1099,6 +1101,7 @@ public ValidationResult walk(ExecutionContext executionContext, String input, In
/**
* Walk the input.
*
* @param <T> the result type
* @param executionContext the execution context
* @param input the input
* @param inputFormat the input format
Expand Down Expand Up @@ -1132,6 +1135,7 @@ public ValidationResult walk(ExecutionContext executionContext, String input, In
/**
* Walk the input.
*
* @param <T> the result type
* @param executionContext the execution context
* @param input the input
* @param inputFormat the input format
Expand Down Expand Up @@ -1160,6 +1164,7 @@ public ValidationResult walk(JsonNode node, boolean validate) {
/**
* Walk the JSON node.
*
* @param <T> the result type
* @param node the input
* @param validate true to validate the input against the schema
* @param outputFormat the output format
Expand Down
63 changes: 40 additions & 23 deletions src/main/java/com/networknt/schema/JsonSchemaFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@
import com.networknt.schema.resource.SchemaMapper;
import com.networknt.schema.resource.SchemaMappers;
import com.networknt.schema.serialization.JsonMapperFactory;
import com.networknt.schema.serialization.JsonNodeReader;
import com.networknt.schema.serialization.YamlMapperFactory;
import com.networknt.schema.serialization.node.JsonNodeFactoryFactory;
import com.networknt.schema.utils.JsonNodes;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -56,7 +55,7 @@ public class JsonSchemaFactory {
public static class Builder {
private ObjectMapper jsonMapper = null;
private ObjectMapper yamlMapper = null;
private JsonNodeFactoryFactory jsonNodeFactoryFactory = null;
private JsonNodeReader jsonNodeReader = null;
private String defaultMetaSchemaIri;
private final ConcurrentMap<String, JsonMetaSchema> metaSchemas = new ConcurrentHashMap<String, JsonMetaSchema>();
private SchemaLoaders.Builder schemaLoadersBuilder = null;
Expand All @@ -65,25 +64,47 @@ public static class Builder {
private JsonMetaSchemaFactory metaSchemaFactory = null;

/**
* Configures the {@link JsonNodeFactoryFactory} to use.
* Sets the json node reader to read the data.
* <p>
* To get location information from {@link JsonNode} the
* {@link com.networknt.schema.serialization.node.LocationJsonNodeFactoryFactory}
* can be used.
* If set this takes precedence over the configured json mapper and yaml mapper.
* <p>
* A location aware object reader can be created using JsonNodeReader.builder().locationAware().build().
*
* @param jsonNodeFactoryFactory the factory to create json node factories
* @param jsonNodeReader the object reader
* @return the builder
*/
public Builder jsonNodeFactoryFactory(JsonNodeFactoryFactory jsonNodeFactoryFactory) {
this.jsonNodeFactoryFactory = jsonNodeFactoryFactory;
public Builder jsonNodeReader(JsonNodeReader jsonNodeReader) {
this.jsonNodeReader = jsonNodeReader;
return this;
}

/**
* Sets the json mapper to read the data.
* <p>
* If the object reader is set this will not be used.
* <p>
* This is deprecated use a object reader instead.
*
* @param jsonMapper the json mapper
* @return the builder
*/
@Deprecated
public Builder jsonMapper(final ObjectMapper jsonMapper) {
this.jsonMapper = jsonMapper;
return this;
}

/**
* Sets the yaml mapper to read the data.
* <p>
* If the object reader is set this will not be used.
* <p>
* This is deprecated use a object reader instead.
*
* @param yamlMapper the yaml mapper
* @return the builder
*/
@Deprecated
public Builder yamlMapper(final ObjectMapper yamlMapper) {
this.yamlMapper = yamlMapper;
return this;
Expand Down Expand Up @@ -151,7 +172,7 @@ public JsonSchemaFactory build() {
return new JsonSchemaFactory(
jsonMapper,
yamlMapper,
jsonNodeFactoryFactory,
jsonNodeReader,
defaultMetaSchemaIri,
schemaLoadersBuilder,
schemaMappersBuilder,
Expand All @@ -164,7 +185,7 @@ public JsonSchemaFactory build() {

private final ObjectMapper jsonMapper;
private final ObjectMapper yamlMapper;
private final JsonNodeFactoryFactory jsonNodeFactoryFactory;
private final JsonNodeReader jsonNodeReader;
private final String defaultMetaSchemaIri;
private final SchemaLoaders.Builder schemaLoadersBuilder;
private final SchemaMappers.Builder schemaMappersBuilder;
Expand All @@ -180,7 +201,7 @@ public JsonSchemaFactory build() {
private JsonSchemaFactory(
ObjectMapper jsonMapper,
ObjectMapper yamlMapper,
JsonNodeFactoryFactory jsonNodeFactoryFactory,
JsonNodeReader jsonNodeReader,
String defaultMetaSchemaIri,
SchemaLoaders.Builder schemaLoadersBuilder,
SchemaMappers.Builder schemaMappersBuilder,
Expand All @@ -197,7 +218,7 @@ private JsonSchemaFactory(
}
this.jsonMapper = jsonMapper;
this.yamlMapper = yamlMapper;
this.jsonNodeFactoryFactory = jsonNodeFactoryFactory;
this.jsonNodeReader = jsonNodeReader;
this.defaultMetaSchemaIri = defaultMetaSchemaIri;
this.schemaLoadersBuilder = schemaLoadersBuilder;
this.schemaMappersBuilder = schemaMappersBuilder;
Expand Down Expand Up @@ -290,7 +311,7 @@ public static Builder builder(final JsonSchemaFactory blueprint) {
.defaultMetaSchemaIri(blueprint.defaultMetaSchemaIri)
.jsonMapper(blueprint.jsonMapper)
.yamlMapper(blueprint.yamlMapper)
.jsonNodeFactoryFactory(blueprint.jsonNodeFactoryFactory);
.jsonNodeReader(blueprint.jsonNodeReader);
if (blueprint.schemaLoadersBuilder != null) {
builder.schemaLoadersBuilder = SchemaLoaders.builder().with(blueprint.schemaLoadersBuilder);
}
Expand Down Expand Up @@ -442,18 +463,18 @@ protected JsonMetaSchema loadMetaSchema(String iri, SchemaValidatorsConfig confi
}

JsonNode readTree(String content, InputFormat inputFormat) throws IOException {
if (this.jsonNodeFactoryFactory == null) {
if (this.jsonNodeReader == null) {
return getObjectMapper(inputFormat).readTree(content);
} else {
return JsonNodes.readTree(getObjectMapper(inputFormat), content, this.jsonNodeFactoryFactory);
return this.jsonNodeReader.readTree(content, inputFormat);
}
}

JsonNode readTree(InputStream content, InputFormat inputFormat) throws IOException {
if (this.jsonNodeFactoryFactory == null) {
if (this.jsonNodeReader == null) {
return getObjectMapper(inputFormat).readTree(content);
} else {
return JsonNodes.readTree(getObjectMapper(inputFormat), content, this.jsonNodeFactoryFactory);
return this.jsonNodeReader.readTree(content, inputFormat);
}
}

Expand Down Expand Up @@ -627,10 +648,6 @@ ObjectMapper getJsonMapper() {
return this.jsonMapper != null ? this.jsonMapper : JsonMapperFactory.getInstance();
}

JsonNodeFactoryFactory getJsonNodeFactoryFactory() {
return this.jsonNodeFactoryFactory;
}

/**
* Creates a schema validators config.
*
Expand Down
Loading