mbknor / mbknor-jackson-jsonSchema

Generate JSON Schema with Polymorphism using Jackson annotations
MIT License
235 stars 79 forks source link

JsonPropertyDescription is ignored in polymorphic classes when implemented via traits #116

Closed afolgado closed 4 years ago

afolgado commented 4 years ago

This is possibly related to #105

When using polymorphic classes, the annotation JsonPropertyDescription is ignored when they're implemented via traits. If I use abstract classes, it's working properly.

This is a minimal example. Given the classes:

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonPropertyDescription
import com.fasterxml.jackson.annotation.JsonTypeInfo

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = 'type', visible = true)
abstract class AbstractClass {

    @JsonPropertyDescription('This description should be set on implementing classes')
    String needsDescriptionField

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    String type

}

class ExtendingClass extends AbstractClass {

}

The method:

    void descriptions_is_missing_in_traits() {
        ObjectMapper mapper = new ObjectMapper()
        JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper)
        JsonNode schema

        schema = generator.generateJsonSchema(ExtendingClass)
        println "Description is present in abstracts: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema)
    }

outputs:

Description is present in abstracts: {
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "ExtendingClass",
  "type" : "object",
  "additionalProperties" : false,
  "properties" : {
    "type" : {
      "type" : "string",
      "enum" : [ "ExtendingClass" ],
      "default" : "ExtendingClass"
    },
    "needsDescriptionField" : {
      "type" : "string",
      "description" : "This description should be set on implementing classes"
    }
  },
  "required" : [ "type" ]
}

Please note that the "description field" is correctly transcribed to the schema. Now, if I use traits insteads of abstract classes:

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonPropertyDescription
import com.fasterxml.jackson.annotation.JsonTypeInfo

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = 'type', visible = true)
trait TraitClass {

    @JsonPropertyDescription('This description should be set on implementing classes')
    String needsDescriptionField

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    String type

}

class ImplementingClass implements TraitClass {

}

the method:

    @Test
    void descriptions_is_missing_in_traits() {
        ObjectMapper mapper = new ObjectMapper()
        JsonSchemaGenerator generator = new JsonSchemaGenerator(mapper)
        JsonNode schema

        schema = generator.generateJsonSchema(ImplementingClass)
        println "Description is missing in traits: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema)
    }

outputs:

Description is missing in traits: {
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "ImplementingClass",
  "type" : "object",
  "additionalProperties" : false,
  "properties" : {
    "type" : {
      "type" : "string",
      "enum" : [ "ImplementingClass" ],
      "default" : "ImplementingClass"
    },
    "needsDescriptionField" : {
      "type" : "string"
    }
  },
  "required" : [ "type" ]
}

Note that "needsDescriptionField" lacks the "description" field.

afolgado commented 4 years ago

As a workaround, it looks like adding "@JsonProperty('needsDescriptionField')" to the trait property solves the problem.

mbknor commented 4 years ago

I have confirmed this problem using Scala. (I'm not sure which language you refer to saying "Trait" because your example code does not look like Scala :))

This problem is not fixable in mbknor-jackson-jsonSchema. When looking for jackson-annotatations for a specific property, I use the Jackson-method com.fasterxml.jackson.databind.BeanProperty.getAnnotation().

This method does not return the @JsonPropertyDescription-annotation in this trait-situation. If Jackson (or the language-specific module) returned the annotation, everything would work..