Skip to content

VisitorContext results in incomplete json schema output #47

@gadams00

Description

@gadams00

In version 2.4.1, VisitorContext was added, which keeps track of visited JavaTypes in a static HashSet, with static methods to add to and get from the static HashSet. Because of this, if you use SchemaFactoryWrapper to generate json schema multiple times during a given run of the JVM, you may get references along the lines of "$ref" : "urn:jsonschema:test:JsonSchemaTest:Bar" when no such id exists in the json schema document generated. To make matters worse, because VisitorContext is all static, there's no way to work around the problem.

here's a quick test case that produces the issue:

package test;

import java.io.StringWriter;

import org.junit.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;

public class JsonSchemaTest {


    class Foo {
        private String fooProp1;
        private int fooProp2;
        private Bar fooProp3;

        public String getFooProp1() {
            return fooProp1;
        }

        public void setFooProp1(String fooProp1) {
            this.fooProp1 = fooProp1;
        }

        public int getFooProp2() {
            return fooProp2;
        }

        public void setFooProp2(int fooProp2) {
            this.fooProp2 = fooProp2;
        }

        public Bar getFooProp3() {
            return fooProp3;
        }

        public void setFooProp3(Bar fooProp3) {
            this.fooProp3 = fooProp3;
        }
    }

    class Bar {
        private String barProp1;
        private int barProp2;

        public String getBarProp1() {
            return barProp1;
        }

        public void setBarProp1(String barProp1) {
            this.barProp1 = barProp1;
        }

        public int getBarProp2() {
            return barProp2;
        }

        public void setBarProp2(int barProp2) {
            this.barProp2 = barProp2;
        }
    }

    class Qwer {
        private String qwerProp1;
        private Bar qwerProp2;

        public String getQwerProp1() {
            return qwerProp1;
        }

        public void setQwerProp1(String qwerProp1) {
            this.qwerProp1 = qwerProp1;
        }

        public Bar getQwerProp2() {
            return qwerProp2;
        }

        public void setQwerProp2(Bar qwerProp2) {
            this.qwerProp2 = qwerProp2;
        }
    }

    @Test
    public void testSchemaGeneration() throws Exception {
        printJsonSchema(Foo.class);
        printJsonSchema(Qwer.class);
    }

    private void printJsonSchema(Class<?> clazz) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
        SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
        mapper.acceptJsonFormatVisitor(
                mapper.constructType(
                        clazz), visitor);
        StringWriter sr = new StringWriter();
        mapper.writeValue(sr, visitor.finalSchema());
        System.out.println(sr.toString());
    }

}

output:

{
  "type" : "object",
  "id" : "urn:jsonschema:test:JsonSchemaTest:Foo",
  "properties" : {
    "fooProp3" : {
      "type" : "object",
      "id" : "urn:jsonschema:test:JsonSchemaTest:Bar",
      "properties" : {
        "barProp1" : {
          "type" : "string"
        },
        "barProp2" : {
          "type" : "integer"
        }
      }
    },
    "fooProp2" : {
      "type" : "integer"
    },
    "fooProp1" : {
      "type" : "string"
    }
  }
}
{
  "type" : "object",
  "id" : "urn:jsonschema:test:JsonSchemaTest:Qwer",
  "properties" : {
    "qwerProp2" : {
      "type" : "object",
      "$ref" : "urn:jsonschema:test:JsonSchemaTest:Bar"
    },
    "qwerProp1" : {
      "type" : "string"
    }
  }
}

Note that the second object in the output is incomplete."$ref" : "urn:jsonschema:test:JsonSchemaTest:Bar" refers to an id from the prior schema generation operation that got statically cached.

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