jackson-module-jsonSchema icon indicating copy to clipboard operation
jackson-module-jsonSchema copied to clipboard

Generated JSON Schema incorrect for @JsonIdentityReference(alwaysAsId = true)

Open harmenwessels opened this issue 8 years ago • 0 comments

Hi,

I am trying to create a JSON representation of a datamodel and want to use a JSON Schema to validate the contents. When using the JSON Schema generated by the jsonSchema module I run into trouble when I have a property which is an identify reference (@JsonIdentityReference(alwaysAsId = true)).

For example when we have three classes: ManagingObject (which manages everything), ReferencedObject (the object which is managed by ManagingObject) and ReferencingObject (an object which references to ReferencedObject and is also managed by ManagingObject):

public class ManagingObject {
    @JsonManagedReference
    public Vector<ReferencedObject> referencedObjects;
    
    @JsonManagedReference
    public ReferencingObject referencingObject;
    
    public ManagingObject() {
        referencedObjects = new Vector<ReferencedObject>();
    }
}
@JsonIdentityInfo(property="id", generator=ObjectIdGenerators.PropertyGenerator.class)
public class ReferencedObject {
    public UUID id;
    
    public String someOtherProperty;
    
    public ReferencedObject() {
        id = UUID.randomUUID();
    }
}
public class ReferencingObject {
    @JsonIdentityReference(alwaysAsId = true)
    public ReferencedObject referencedObject;
}

When I then create a sample JSON using the following code:

// Create an example JSON.
ObjectMapper objectMapper = new ObjectMapper();
ManagingObject mo = new ManagingObject();
// Create the ReferencedObject and add it to the ManagingObject collection.
ReferencedObject ro = new ReferencedObject();
ro.someOtherProperty = "Something";
mo.referencedObjects.add(ro);
// Create the ReferencingObject and set its referencedObject and also add a reference in the ManagingObject to it.
ReferencingObject rco = new ReferencingObject();
rco.referencedObject = ro;
mo.referencingObject = rco;
// Create a JSON representation of the ManagingObject.
System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(mo));

Then the output is what I would expect (in the ReferencingObject it points directly to the id and doesn't include the full referencedObject):

{
  "referencedObjects" : [ {
    "id" : "de0fb81e-014d-480a-8b65-01ce2daf719f",
    "someOtherProperty" : "Something"
  } ],
  "referencingObject" : {
    "referencedObject" : "de0fb81e-014d-480a-8b65-01ce2daf719f"
  }
}

But when I then generate a JSON Schema using the following code:

// Create the JSON Schema.
ObjectMapper objectMapper = new ObjectMapper();
JsonSchemaGenerator jsonSchemaGenerator = new JsonSchemaGenerator(objectMapper);
JsonNode jsonSchema = jsonSchemaGenerator.generateJsonSchema(ManagingObject.class);
System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));

Then the output is not what I would expect for the referencedObject in ReferencingObject (unless I misunderstand):

{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "Managing Object",
  "type" : "object",
  "additionalProperties" : false,
  "properties" : {
    "referencedObjects" : {
      "type" : "array",
      "items" : {
        "$ref" : "#/definitions/ReferencedObject"
      }
    },
    "referencingObject" : {
      "$ref" : "#/definitions/ReferencingObject"
    }
  },
  "definitions" : {
    "ReferencedObject" : {
      "type" : "object",
      "additionalProperties" : false,
      "properties" : {
        "id" : {
          "type" : "string"
        },
        "someOtherProperty" : {
          "type" : "string"
        }
      }
    },
    "ReferencingObject" : {
      "type" : "object",
      "additionalProperties" : false,
      "properties" : {
        "referencedObject" : {
          "$ref" : "#/definitions/ReferencedObject"
        }
      }
    }
  }
}

When I look at the ReferencingObject definition of the schema I see a JSON Pointer to the ReferencedObject definition for the 'referencedObject' property, but in the example JSON the id is directly mapped (not a full JSON representation of the ReferencedObject). So the JSON produced is not valid according the JSON Schema on the same object model.

Am I doing something wrong or weird here? Or should the JSON Schema look a bit different for the properties which are marked with the annotation @JsonIdentityReference(alwaysAsId = true) ?

harmenwessels avatar Sep 15 '17 20:09 harmenwessels