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

VisitorContext results in incomplete json schema output #47

Closed
gadams00 opened this issue Oct 21, 2014 · 1 comment
Closed

VisitorContext results in incomplete json schema output #47

gadams00 opened this issue Oct 21, 2014 · 1 comment

Comments

@gadams00
Copy link

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.

@cowtowncoder
Copy link
Member

Ouch. Static anything is pretty stupid thing to do... All objects should be bound to call life-cycle.

Thank you for reporting this, and apologies for letting such a stupid flaw make it in.

But fortunately this seems to be more of an oversight with calls; will fix this shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants