Skip to content

NPE with oneOf and custom URI Fetcher or Factory #509

@chrswk

Description

@chrswk

Hi

I tried to update my project from 1.0.52 to 1.0.66 and now get a NPE with schemas that use oneOf with a custom URI fetcher. Or at least I think it's related to the URI fetcher, since oneOf with $ref to a definition, etc. still work fine.

java.lang.NullPointerException: Cannot invoke "com.networknt.schema.JsonSchema.getSchemaNode()" because the return value of "com.networknt.schema.JsonSchema.getParentSchema()" is null
    at com.networknt.schema.utils.JsonNodeUtil.equalsToSchemaType(JsonNodeUtil.java:88)
    at com.networknt.schema.TypeValidator.validate(TypeValidator.java:120)
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:285)
    at com.networknt.schema.JsonSchemaRef.validate(JsonSchemaRef.java:38)
    at com.networknt.schema.RefValidator.validate(RefValidator.java:139)
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:285)
    at com.networknt.schema.OneOfValidator.validate(OneOfValidator.java:160)
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:285)
    at com.networknt.schema.PropertiesValidator.validate(PropertiesValidator.java:68)
    at com.networknt.schema.JsonSchema.validate(JsonSchema.java:285)
    at com.networknt.schema.BaseJsonValidator.validate(BaseJsonValidator.java:114)
    ...

The same code does not produce a NPE with release 1.0.57, so I guess it has something to do with the changes in 1.0.58. Here is a test case to reproduce the issue:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Charsets;
import com.google.common.io.CharSource;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SpecVersion;
import com.networknt.schema.ValidationMessage;
import com.networknt.schema.uri.URIFactory;
import com.networknt.schema.uri.URIFetcher;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Set;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

public class CustomUriTest {
    @Test
    public void customUri() throws Exception {
        /* Given */
        final JsonSchemaFactory factory = buildJsonSchemaFactory();
        final JsonSchema schema = factory.getSchema("""
            {
                "$schema": "https://json-schema.org/draft/2019-09/schema",
                "type": "object",
                "additionalProperties": false,
                "properties": {
                    "customAnyOf": {
                        "anyOf": [
                            {"type": "null"},
                            {"$ref": "custom:date"}
                        ]
                    },
                    "customOneOf": {
                        "oneOf": [
                            {"type": "null"},
                            {"$ref": "custom:date"}
                        ]
                    }
                }
            }""");
        final ObjectMapper mapper = new ObjectMapper();
        final JsonNode value = mapper.readTree("""
            {
                "customAnyOf": null,
                "customOneOf": null
            }""");

        /* When */
        final Set<ValidationMessage> errors = schema.validate(value);

        /* Then */
        assertThat(errors.isEmpty(), is(true));
    }

    private JsonSchemaFactory buildJsonSchemaFactory() {
        return JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909))
            .uriFetcher(new CustomUriFetcher(), "custom").uriFactory(new CustomUriFactory(), "custom").build();
    }

    private static class CustomUriFetcher implements URIFetcher {
        private static final String SCHEMA = """
            {"$schema": "https://json-schema.org/draft/2019-09/schema","$id":"custom:date","type":"string","format":"date"}""";

        @Override
        public InputStream fetch(final URI uri) throws IOException {
            return CharSource.wrap(SCHEMA).asByteSource(Charsets.UTF_8).openStream();
        }
    }

    private static class CustomUriFactory implements URIFactory {
        @Override
        public URI create(final String uri) {
            return URI.create(uri);
        }

        @Override
        public URI create(final URI baseURI, final String segment) {
            return baseURI.resolve(segment);
        }
    }
}

anyOf is just included here because I was interested to know if it's affected and the answer is no.

Thanks
Chris

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions