Git Product home page Git Product logo

jackson-module-jsonschema's Introduction

Jackson JSON Schema Module

This module supports the creation of a JSON Schema (v3)

Note that since JSON Schema draft version 3 and 4 are incompatible, this module CAN NOT, as-is, support v4. There is another module mbknor-jackson-jsonSchema that does support v4, however.

It is possible that in future this repo could have 2 different modules; one for v3, another v4. And if necessary, more if future revisions also prove incompatible.

Status

Build Status Maven Central Javadoc

Version 2.4 was considered the first stable version of the module.

Two modules (with Jackson 2.15)

Starting with upcoming Jackson 2.15, this repository contains TWO versions of the module:

  1. Old JSON Schema module com.fasterxml.jackson.module:jackson-module-jsonSchema (since 2.0)
  2. New JSON Schema module com.fasterxml.jackson.module:jackson-module-jsonSchema-jakarta (2.15+)

depending on whether system needs to work with "old" javax/JAXB APIs (first module) or newer "Jakarta" APIs.

Future plans (lack thereof)

Due to lack of support by community, this module is NOT planned to be supported beyond Jackson 2.x -- no work has been done for it to work with future Jackson 3.0. Users are encouraged to use more up-to-date JSON Schema support tools.

Example Usage

(from TestGenerateJsonSchema)

simply add a dependency "com.fasterxml.jackson.module:jackson-module-jsonSchema:2.15.0" or "com.fasterxml.jackson.module:jackson-module-jsonSchema-jakarta:2.15.0" for the jakarta namespace

and for gradle, at least, you can simply add mavenLocal() to your repositories. Maven should resolve the dependency from its local repo transparently.

ObjectMapper mapper = new ObjectMapper();
// configure mapper, if necessary, then create schema generator
JsonSchemaGenerator schemaGen = new JsonSchemaGenerator(mapper);
JsonSchema schema = schemaGen.generateSchema(SimpleBean.class);

This will yield a java pojo representing a JSON Schema, which can itself easily be serialized with jackson, or configured with java. Customizing the generation should be simply a matter of locating the particular stage of generation you want to override, and replacing or extending that particular object in the dependency injection cycle in schemafactory wrapper.

Adding Property Processing

See com.fasterxml.jackson.module.jsonSchema.customProperties.TitleSchemaFactoryWrapper for an example of writing custom schema properties.

Required Fields

JSON Schema has the ability to mark fields as required. This module supports this via the @JsonProperty(required = true) field annotation.

JsonSchema Hypermedia support

Generic support

Current implementation is partial for IETF published draft v4 (http://json-schema.org/latest/json-schema-hypermedia.html).

Currently 2 aspects of IETF supported:

  • pathStart - URI that defines what the instance's URI MUST start with in order to validate.
  • links - associated Link Description Objects with instances.

You can enable HypermediaSupport using com.fasterxml.jackson.module.jsonSchema.customProperties.HyperSchemaFactoryWrapper. Example:

HyperSchemaFactoryWrapper personVisitor = new HyperSchemaFactoryWrapper();
ObjectMapper mapper = new ObjectMapper();
mapper.acceptJsonFormatVisitor(Person.class, personVisitor);
JsonSchema personSchema = personVisitor.finalSchema();

By default all default values for Link Description Object are ignored in the output (method = GET, enctype = application/json, mediaType = application/json), to enable default setIgnoreDefaults(true)

Describing JSON hyper-schema

You can describe hyperlinks, using annotations @JsonHyperSchema & @Link

 public class Pet {
     public String genus;
 }

 @JsonHyperSchema(
     pathStart = "http://localhost:8080/persons/",
     links = {
         @Link(href = "{name}", rel = "self"),
         @Link(href = "{name}/pet", rel = "pet", targetSchema = Pet.class)
 })
 public class Person {
     public String name;
     public String hat;
 }

Would generate following values:

{
  "type" : "object",
  "pathStart" : "http://localhost:8080/persons/",
  "links" : [ {
    "href" : "http://localhost:8080/persons/{name}",
    "rel" : "self"
  }, {
    "href" : "http://localhost:8080/persons/{name}/pet",
    "rel" : "pet",
    "targetSchema" : {
      "type" : "object",
      "properties" : {
        "genus" : {
          "type" : "string"
        }
      }
    }
  } ],
  "properties" : {
    "name" : {
      "type" : "string"
    },
    "hat" : {
      "type" : "string"
    }
  }
}

More

Check out Project Wiki for more information (javadocs, downloads).

jackson-module-jsonschema's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jackson-module-jsonschema's Issues

How to specify arbitrary custom properties?

For boolean (checkbox) fields, I need to add, instead of "title", a property called "inlinetitle" as a hint for the frontend renderer, in this case jsonform.

How can I specify these sorts of custom properties?

Using @XmlEnum to generate an enum of type Integer in json schema

I have the following Java enum:

@XmlType
@XmlEnum(Integer.class)
public enum DefaultMessageVersion
{
@XmlEnumValue("1") ONE;
}

That is producing the following json schema snippet:

"defaultMessageVersion" : {
"type" : "string",
"enum" : [ "1" ]
}

This is because (I believe) Jackson ignores the @XmlEnum annotation. I would like the outputted snippet to have "type" : "integer" (or int? I'm not 100% sure which it is). I'm going to attempt to write the functionality myself, but would appreciate any pointers on where to get started, or a head-up if I'm just wrong about why it's not working.

VisitorContext results in incomplete json schema output

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.

Improved schema for maps

Currently map schemas are produced as empty objects.
com.fasterxml.jackson.module.jsonSchema.factories.MapVisitor comments say: "
/**

  • While JSON Schema does not have notion of "Map" type (unlimited property
  • names), Jackson has, so the distinction is exposed. We will need
  • to handle it here, produce JSON Schema Object type.
    */
    "
    well, i think this can easily be achieved using "additionalProperties", for example:

private Map<?,Bolean> mapOfBooleans the output could be:

{
"type":"object",
"properties":{
"mapOfBooleans ":{
"type":"object",
"additionalProperties": {
"type": "boolean"
}
}
}
}

Json Schema version

Hi,

Can I have json schema version 4 using this module? Currently I am getting version 3.

Thanks.

Support for "media" property

Section 4.3 of the JSON Schema specification mentions the media property, which is used to give additional hints about the semantics of non-JSON data that is encoded as a JSON string. For example:

{
    "type": "string",
    "media": {
        "binaryEncoding": "base64",
        "type": "image/png"
    }
}

I think an annotation of some sort might help perhaps. The serializer can check to see if an annotation is present on that property and if so, it can generate the media property.

Schema generates multiple type qualifiers for Date, int, long data types

public class Employee {

  protected Date birthDt;
  protected String name;
  public Date getBirthDt() {
    return birthDt;
  }

  public void setBirthDt(Date value) {
    this.birthDt = value;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public static void main(String[] args) throws Exception {
    ObjectMapper mapper = new ObjectMapper();
    JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper);
    JsonSchema jsonSchema = generator.generateSchema(Employee.class);
    System.out.println(mapper.writeValueAsString(jsonSchema));
  }
}

The code produces the JSON schema with redundant types for Date field.

{"type": "object", "properties": {
  "name": {
    "type": "string"
  },
  "birthDt": {
    "type": "number",
    "format": "UTC_MILLISEC",
    "type": "integer"
  }
}}

Add support to @JsonView

I'd like to create a JSON schema with JsonView annotations as follows:

ObjectMapper mapper = new ObjectMapper();

// view configuration
mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
mapper.setConfig(mapper.getSerializationConfig().withView(MyView.class));

SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(mapper.constructType(MyBean.class), visitor);
JsonSchema jsonSchema = visitor.finalSchema();

Currently the view configuration does not seem to have effect on the produced schema.

Incomplete type definition for array/Collection properties

NOTE: cleaved off of #34


This bug seems not to be completely fixed. It doesn't throw a NPE anymore, but it doesn't generate the schema correctly either. It just generates:

{
    "type":"array"
}

I extended the test to use a collection of nested beans, and expected to see the schema of the nested items, e.g.:

    {
      "type" : "array",
      "items" : {
        "type" : "object",
        "properties" : {
          "property1" : {
            "type" : "integer"
          },
          "property2" : {
            "type" : "string"
          }
        }
      }
    }

See updated test: greyfairer@2a9b859

Inconsistent json-schema output for mac vs sles11

I'm using jackson to generate json schema strings from POJOs with some code that looks like this:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule( new JaxbAnnotationModule() );
SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
try
{
  for (Class<?> annotatedClass : annotatedClasses)
  {
    mapper.acceptJsonFormatVisitor(annotatedClass, visitor);
    JsonSchema jsonSchema = visitor.finalSchema();
    String schemaString = mapper.writerWithDefaultPrettyPrinter()
        .writeValueAsString(jsonSchema);

When I run this code on my linux machine for some POJOs (I'll use one as a specific example) I get the incomplete schema below:

{
"type" : "object",
"id" : "urn:jsonschema:com:emc:brs:policy:msg:ds:CreateDataSourceRequest",
"properties" : {
"className" : {
"type" : "string",
"required" : true
},
"messageVersion" : {
"type" : "string",
"required" : true,
"description" : "The version of this message",
"enum" : [ "1" ]
},
"dataSource" : {
"type" : "object",
"$ref" : "urn:jsonschema:com:emc:brs:policy:msg:DataSource",
}
}
}

When my co-worker runs the exact same code on his mac, he gets the desired output schema:

{
"type" : "object",
"id" : "urn:jsonschema:com:emc:brs:policy:msg:ds:CreateDataSourceRequest",
"properties" : {
"className" : {
"type" : "string",
"required" : true
},
"messageVersion" : {
"type" : "string",
"required" : true,
"description" : "The version of this message",
"enum" : [ "1" ]
},
"dataSource" : {
"type" : "object",
"id" : "urn:jsonschema:com:emc:brs:policy:msg:DataSource",
"properties" : {
"hosts" : {
"type" : "array",
"required" : true,
"description" : "Reference to the credentials object if applicable",
"items" : {
"type" : "object",
"id" : "urn:jsonschema:com:emc:brs:policy:msg:Host",
"properties" : {
"hostname" : {
"type" : "string"
},
"ipv6Address" : {
"type" : "string"
},
"name" : {
"type" : "string",
"description" : "Optional alias or name of the object"
},
"ipv4Address" : {
"type" : "string"
},
"osType" : {
"type" : "string"
},
"attributes" : {
"type" : "object",
"description" : "List of attributes for the object",
"additionalProperties" : {
"type" : "string"
}
},
"uuid" : {
"type" : "string",
"required" : true,
"description" : "Unique id of this object"
},
"tags" : {
"type" : "object",
"description" : "List of tags for the object",
"additionalProperties" : {
"type" : "string"
}
}
}
}
},
"paths" : {
"type" : "array",
"required" : true,
"description" : "List of paths and/or compound paths to back up",
"items" : {
"type" : "string"
}
},
"name" : {
"type" : "string",
"description" : "Optional alias or name of the object"
},
"options" : {
"type" : "object",
"id" : "urn:jsonschema:com:emc:brs:policy:msg:Options",
"properties" : {
"name" : {
"type" : "string",
"description" : "Optional alias or name of the object"
},
"flags" : {
"type" : "object",
"additionalProperties" : {
"type" : "string"
}
},
"attributes" : {
"type" : "object",
"description" : "List of attributes for the object",
"additionalProperties" : {
"type" : "string"
}
},
"pid" : {
"type" : "integer"
},
"uuid" : {
"type" : "string",
"required" : true,
"description" : "Unique id of this object"
},
"version" : {
"type" : "string"
},
"tags" : {
"type" : "object",
"description" : "List of tags for the object",
"additionalProperties" : {
"type" : "string"
}
}
}
},
"attributes" : {
"type" : "object",
"description" : "List of attributes for the object",
"additionalProperties" : {
"type" : "string"
}
},
"uuid" : {
"type" : "string",
"required" : true,
"description" : "Unique id of this object"
},
"creds" : {
"type" : "object",
"$ref" : "urn:jsonschema:com:emc:brs:policy:msg:Creds"
},
"dataSourceType" : {
"type" : "string",
"required" : true,
"description" : "The type of data source",
"enum" : [ "FILE_SYSTEM", "FILE_SYSTEM_TRADITIONAL", "FILE_SYSTEM_INCREMENTAL_FOREVER", "DB2", "EXCHANGE", "HYPER_V", "INTERNAL", "LOTUS", "NAS_DEVICE", "ORACLE", "SAP", "SHAREPOINT", "SQL", "SYBASE", "VMWARE", "UNKNOWN" ]
},
"tags" : {
"type" : "object",
"description" : "List of tags for the object",
"additionalProperties" : {
"type" : "string"
}
}
}
}
}
}

I am at a loss for what could be causing this beyond some sort of nasty/inconsistent interaction between Jackson and the JVM implementations. Have you seen anything like this before? Is there anything obvious I should try as a workaround?

JSON schema generation with Jackson goes into infinite loop

(moved from: FasterXML/jackson-databind#54 )


It might be that I'm missing an obvious annotation in Jackson but I have following class

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.jsonschema.JsonSchema;

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Loop {

 private String name;
 private Loop otherLoop;

 public String getName() { return name; }
 public void setName(String name) { this.name = name; }
 public Loop getOtherLoop() { return otherLoop; }
 public void setOtherLoop(Loop otherLoop) { this.otherLoop = otherLoop; }

 public static void main(String[] args) throws Exception {
  Loop parent = new Loop();
  parent.setName("parent");

  Loop child = new Loop();
  child.setName("child");
  child.setOtherLoop(parent);

  ObjectMapper mapper = new ObjectMapper();
  System.out.println(mapper.writeValueAsString(child));

  JsonSchema jsonSchema = mapper.generateJsonSchema(Loop.class);
  System.out.println(mapper.writeValueAsString(jsonSchema));
 }
}

and when I run it using Jackson 2 it goes into an infinite loop

{"name":"child","otherLoop":{"name":"parent"}}

Exception in thread "main" java.lang.StackOverflowError
at com.fasterxml.jackson.databind.cfg.MapperConfig.isEnabled(MapperConfig.java:106)
at com.fasterxml.jackson.databind.SerializationConfig.getAnnotationIntrospector(SerializationConfig.java:382)
at com.fasterxml.jackson.databind.SerializerProvider.getAnnotationIntrospector(SerializerProvider.java:307)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.createContextual(BeanSerializerBase.java:318)
at com.fasterxml.jackson.databind.SerializerProvider._handleContextual(SerializerProvider.java:971)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:447)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:619)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)

at  com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.getSchema(BeanSerializerBase.java:621)

Any ideas, workarounds?!

How can I use the TitleSchemaFactoryWrapper to generate titles matching property names?

I'm having trouble working out how I'd gain access to the property name in the context of the TitleSchemaFactoryWrapper. Currently the example writes out the title using the canonical name of the class. I'd like to use the actual property name on the POJO (and ultimately apply some string manipulations to transform it from camelCase to Title Case.)

It seems like the schema and the type don't have immediate access to the name of the property (although of course somehow the property is eventually getting written into the schema, but not as a title.) I'm reviewing the code and trying to understand but some guidance here would be very helpful.

Support polymorphism on schema generation

(moved from: FasterXML/jackson-databind#41 )


t would be nice to support polymorphism on schema generation.
Currently, the generated schema doesn't provides information on subtypes with the above case .

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "type")  
@JsonSubTypes({  
    @Type(value = subtypeA.class, name = "A"),
    @Type(value = subtypeB.class, name = "B"),
    @Type(value = subtypeC.class, name = "C")
     }) 
public abstract class ParentType { }

How to specify the "id" URI?

I have two classes: Article and User and their respective schemas are available at:

Since Article.author is of type User, how can I have the correct $ref in the schema? Now I'm getting this:

{
   "type":"object",
   "properties":{
      "id":{
         "type":"integer"
      },
      "title":{
         "type":"string"
      },
      "author":{
         "type":"object",
         "id":"urn:jsonschema:it:saiv:best:common:entity:User",
         "properties":{
            "id":{
               "type":"integer"
            },
            "cn":{
               "type":"string"
            }
         }
      }
   }
}

but I would expect something like:

{
   "type":"object",
   "properties":{
      "id":{
         "type":"integer"
      },
      "title":{
         "type":"string"
      },
      "author":{
          "$ref":"http://localhost:8080/api/users/$schema"
      }
   }
}

This is the code I'm using to generate the schema:

    @GET
    @Path("/$schema")
    @Produces(MediaType.APPLICATION_JSON)
    public String getSchema() throws IOException {
        HyperSchemaFactoryWrapper visitor = new HyperSchemaFactoryWrapper();
        ObjectMapper mapper = new ObjectMapper();
        mapper.acceptJsonFormatVisitor(Article.class, visitor);
        JsonSchema schema = visitor.finalSchema();
        return mapper.writeValueAsString(schema);
    }

Mechanism required to customize schema for object property

If I have a custom annotation on the property of an object, this cannot be visited as the JsonFormatVisitorWrapper takes only the type of the property. I've looked also at subclassing ObjectSchema but since this takes the property name as a String only, seems I'd have to do some reflection to get back to the property itself.

I can see a significant number of use cases of wanting to customize a schema being related to the information associated with an object property (custom annotations, documentation, validation, etc.). My particular use-case is that the schema should provide some information for client-side validation, from the bean validation API.

I've seen threads suggesting that this would be possible (http://jackson-users.ning.com/forum/topics/json-schema-generation-with-jackson-module-jsonschema, http://jackson-users.ning.com/forum/topics/handling-a-custom-annotation-when-generating-json-schema) but I can't see it, myself.

Is there some mechanism I'm missing?

Enum types should generate a schema that includes the possible enum values

Cross posting from my StackOverflow question. After doing some digging it seems like the schema is defaulting to using the bare serialized type rather than properly using the possible enum values.

Link to the question on StackOverflow:
http://stackoverflow.com/questions/27863689/generate-json-schema-from-pojo-with-a-twist

I'm generating a JSON schema from a pojo. My code to generate the schema looks like so:

ObjectMapper mapper = new ObjectMapper();
TitleSchemaFactoryWrapper visitor = new TitleSchemaFactoryWrapper();
mapper.acceptJsonFormatVisitor(clazz, visitor);
JsonSchema schema = visitor.finalSchema();
schemas.put(clazz, mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema));

I'm generating several schemas via the above code. One of the pojos has an internal embedded enum to limit the possible values, like so:

public class MyClass {

    @JsonProperty("name")
    private String name;
    @JsonProperty("startDayOfWeek")
    private MyClass.StartDayOfWeek startDayOfWeek;
    /**
     * The ID of a timezone returned by the timezones route.
     * 
     */
    @JsonProperty("timezone")
    private String timezone;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     * 
     * @return
     *     The startDayOfWeek
     */
    @JsonProperty("startDayOfWeek")
    public MyClass.StartDayOfWeek getStartDayOfWeek() {
        return startDayOfWeek;
    }

    /**
     * 
     * @param startDayOfWeek
     *     The startDayOfWeek
     */
    @JsonProperty("startDayOfWeek")
    public void setStartDayOfWeek(MyClass.StartDayOfWeek startDayOfWeek) {
        this.startDayOfWeek = startDayOfWeek;
    }

    public static enum StartDayOfWeek {

        MONDAY("Monday"),
        TUESDAY("Tuesday"),
        WEDNESDAY("Wednesday"),
        THURSDAY("Thursday"),
        FRIDAY("Friday"),
        SATURDAY("Saturday"),
        SUNDAY("Sunday");
        private final String value;
        private static Map<String, MyClass.StartDayOfWeek> constants = new HashMap<String, MyClass.StartDayOfWeek>();

        static {
            for (MyClass.StartDayOfWeek c: values()) {
                constants.put(c.value, c);
            }
        }

        private StartDayOfWeek(String value) {
            this.value = value;
        }

        @JsonValue
        @Override
        public String toString() {
            return this.value;
        }

        @JsonCreator
        public static MyClass.StartDayOfWeek fromValue(String value) {
            MyClass.StartDayOfWeek constant = constants.get(value);
            if (constant == null) {
                throw new IllegalArgumentException(value);
            } else {
                return constant;
            }
        }

    }

}

The above code should limit the possible String values in the JSON data that's passed around to "Monday", "Tuesday", "Wednesday", etc.

When I run the schema generator on the code in question, I expect to get something like the following schema:

{
  "type" : "object",
  "javaType" : "my.package.MyClass",
  "properties": {
    "startDayOfWeek" : {
      "type" : "string",
      "enum" : [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]
    }
  }
}

but instead I'm getting this:

{
  "type" : "object",
  "id" : "urn:jsonschema:my:package:MyClass",
  "title" : "Lmy/package/MyClass;",
  "properties" : {
    "startDayOfWeek" : {
      "type" : "string"
    }
  }
}

I've done some digging in the Jackson Schema Module source code and figured out that what's happening is Jackson's using ".toString()" as the default serialization method for enum types, but what I need it to do instead is create the line that looks like this based on StartDayOfWeek.values():

"enum" : [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]

Support Scala types

Any chance you have plan to support Scala types? The main problems are in Scala Lists/Maps and Options.

Human readable description support

jackson-annotations now supports @JsonPropertyDescription, cf. FasterXML/jackson-annotations#13

Is the annotation @JsonPropertyDescription supported by jackson-module-jsonSchema? I have tried to generate JSON schema with jackson-module-jsonSchema 2.3.3. However, it ignores @JsonPropertyDescription annotation.

Erroneus assertion found in junit test: TestReadJsonSchema.testDeserializeSimple()

Found an erroneus assertion in this test leading to a weak validation.

Current version: assetEquals of two JsonSchema instances. Probabily equals methods of the instances or nested attributes is not properly defined so assertion succeeds, but the truth is the instances are different and assertion should fail.

Version: 2.3.0-SNAPSHOT

I'll attach a new implementation of the test that show this failed assertion

NPE when generating schema for class with JsonValue annotation over Collection/Array

When trying to generate jsonSchema for the following class, an NPE is raised.
jackson-databind version is 2.2.3.

public class Histogram{

    ...
    @JsonValue
    public Collection<String> asCollection() {...}

    }
java.lang.NullPointerException
    at com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase.acceptJsonFormatVisitor(AsArraySerializerBase.java:255)
    at com.fasterxml.jackson.databind.ser.std.JsonValueSerializer.acceptJsonFormatVisitor(JsonValueSerializer.java:269)
    at com.fasterxml.jackson.databind.ser.std.JsonValueSerializer.acceptJsonFormatVisitor(JsonValueSerializer.java:269)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.acceptJsonFormatVisitor(DefaultSerializerProvider.java:281)
    at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:2673)

Required Fields

JSON Schema has the ability to mark fields as required. This module supports this via the @JsonProperty(required = true) field annotation.

This is not working for me. My object has the following field:

 @XmlAttribute(name = "clientRequestId", required = true)
  protected String clientRequestId;

and the generated output is :

    "clientRequestId" : {
      "type" : "string"
    },

I'm using

    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-jsonSchema</artifactId>
        <version>2.5.1</version>
    </dependency>

Some means of doing parameters

I'm doing an implementation of Swagger 2.0, and Swagger uses JSON Schema to describe not only incoming and outgoing JSON, but also the constraints on any parameters in your REST methods. For example:

public String myRestMethod(@NotNull @min(3) int myNumber) {}

The definition of "myNumber" would be identical to that of a property of a class that had these annotations.

It would really convenient if I could pass in a Java Method or perhaps a JDK 1.8 Parameter object and get JSON Schema for parameters.

Hibernate Validator did exactly this: http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#chapter-method-constraints

Support handling of "unwrapped" POJOs

(note: copied from FasterXML/jackson-databind#271)


For example :

class A { public String text = "text"; }
class B { public @JsonUnwrapped A a = new A(); }

would serialize as :

{"text":"text"}

and the schema would be :

{"type":"object","properties":{"a":{"type":"object","properties":{"text":{"type":"string"}}}}}

but, this is not consistent with the serialized form, the schema should be this :

{"type":"object","properties":{"text":{"type":"string"}}}

schema reference not compatible with tv4

jackson-module-jsonSchema is generating a json schema like this

  "delivery":{  
               "type":"object",
               "id":"urn:jsonschema:io:konik:zugferd:entity:trade:Delivery",
               "properties":{  
                  "shipFrom":{  
                     "type":"object",
                     "$ref":"urn:jsonschema:io:konik:zugferd:entity:TradeParty"
                  },

tv4 is trying to resolve the $ref by fetching the url remotely. When adding a # before the ids and $ref Tv4 is working fine.

  "delivery":{  
               "type":"object",
               "id":"#urn:jsonschema:io:konik:zugferd:entity:trade:Delivery",
               "properties":{  
                  "shipFrom":{  
                     "type":"object",
                     "$ref":"#urn:jsonschema:io:konik:zugferd:entity:TradeParty"
                  },

Who is correct here TV4 or jackson-module-jsonSchema?

Support for Required Fields

Support for required fields would be super useful, since in JSON Schema properties are optional by default and need to be explicitly marked as required.

Related Issue: FasterXML/jackson-databind#230

Related Issue: FasterXML/jackson-module-scala#80

Also, the jsonSchema module does not appear, as I read it, to currently have an effective way to communicating required values to the generated schema. This is information the serializer would have, but the visitor interface doesn't provide the API to tell the visitor about it.

IntegerSchema instead NumberSchema at 2.4.0/2.4.1

HI!

final ObjectMapper mapper = new ObjectMapper();
final JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper);
final JsonSchema schema = generator.generateSchema(Double.class);
mapper.writeValue(System.out, schema);

at version 2.4.0/2.4.1 result:

{"type":"integer"}

at version 2.3.4 result:

{"type":"number"}

Long data type not supported

java.lang.Long datatype fields in the pojo are ending up as "integer" in the JSON schema, java.util.Calender objects are also ending up with a "integer" component in the schema. This leads to loss of precision/data....is this a known issue? Using 2.3.0 version.

jackson-module-jsonSchema has Java 8 test compatibility issue

I've switched from Java7 to Java8, and I see 'TestReadJsonSchema.testReadSimpleTypes' failing.

junit.framework.ComparisonFailure: Schemas for SchemableBasic differ
at com.fasterxml.jackson.module.jsonSchema.TestReadJsonSchema._testSimple(TestReadJsonSchema.java:131)
at com.fasterxml.jackson.module.jsonSchema.TestReadJsonSchema._testSimple(TestReadJsonSchema.java:115)
at com.fasterxml.jackson.module.jsonSchema.TestReadJsonSchema.testReadSimpleTypes(TestReadJsonSchema.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)

This is because ValueTypeSchema uses HashSet as a default implementation, when deserializing JsonSchema, while EnumSerializer uses LinkedHashSet when creating JsonSchema. In Java8 order in HashSet changed, it seems, because build works perfectly fine in Java7.

JSON Schema output is incorrect for nullable/required types

Hi guys,

I'm the author of Metawidget (http://metawidget.org), an Open Source project that generates UIs based on JSON Schema. One of my users is using Jackson to produce his JSON Schema, so that Metawidget can consume it. He tells me that if he has a Java object:

    public class Person {
        public String firstname;
    }

Then Jackson produces a schema of:

    firstname: {
        type: 'string'
    }

However according to the JSON Schema team this is incorrect. Given that String is a nullable field, the schema should instead be:

    firstname: {
        type: [ 'string', 'null' ]
    }

It should only be plain 'string' if the user has further annotated their field with @JsonProperty(required = true) or equivalent. However, if you do that then Jackson produces:

    firstname: {
        type: 'string',
        required: true
    }

Which is also incorrect according to the JSON Schema team ('required' has a quite different meaning in JSON Schema)

Unable to deserialize (extended) Schema

Hi,

It appears that it's not possible to deserialize a schema into an extended ObjectSchema class (ie: class MySchema extends ObjectSchema)

java.lang.IllegalArgumentException: Class com.fasterxml.jackson.module.jsonSchema.types.ObjectSchema is not assignable to com.github.issue.MySchema
    at com.fasterxml.jackson.databind.JavaType._assertSubclass(JavaType.java:408)
    at com.fasterxml.jackson.databind.JavaType.narrowBy(JavaType.java:148)
    at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:179)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:99)
    at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:84)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:948)
    at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:41)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2146)
    at com.github.issue.TestSchema.testSchema(TestSchema.java:28)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)

Thanks!
Sebastien

Maven support?

Quick question - I'm building my project using maven. I wanted to add a dependency, looking at your Readme.md, something along the lines of:

<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsonSchema</artifactId>
<version>2.1.0</version>

I've tried to find your library (jackson-datatype-jsonSchema) in some public maven repository (for example maven central), but I couldn't find it. Did you publish your library to maven central or someplace else? Do you support maven?

Marshalling schema using references

If I understand well the Json schema specs, there seems to be a problem at least when marshalling (probably generating) a schema using references.
$ref should reference a schema that is defined somewhere else and that should have its own type (typically "object"). So when I marshall the containing object I expect to get someting like this :

"Container":{
   "type" : "object",
   "id" : "Container",
   "properties" : {
      "field" : {
         "type" : "integer"
      },
   "contained" : {
      "$ref" : "#/OtherObject"
   }
}

but instead I obtain :

"Container":{
   "type" : "object",
   "id" : "Container",
   "properties" : {
      "field" : {
         "type" : "integer"
      },
   "contained" : {
      "type" : "object",
      "$ref" : "#/OtherObject"
   }
}

with the "contained" property specifing a type while the referenced object already does it.
It is a problem for me as I'm trying to include generated schemas into swagger and swagger only understands that "contained" type is object with no definition attached to it. If I use the expected result, everything seems to work properly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.