Skip to content

Model with constructor annotated with @JsonCreator translates incorrectly in swagger spec #2169

@iyogi

Description

@iyogi

For immutable model classes (no setters), which are deserialised from json using @JsonCreator annotation on constructor, the translation goes wrong in following ways:

  • The @JsonProperty annotating constructor parameter is ignored in favour of class property name
  • If I try to fix above issue my adding a redundant @JsonProperty on the class property (or on the getter method), the translated property in swagger spec incorrectly shows the property as readOnly. The plugin expects a setter method, but there aren't any. But that does not make the property readOnly - since the property is set in the constructor

It appears that the bug is in io.swagger.jackson.ModelResolver (in cohort with io.swagger.models.properties.AbstractProperty) sets the readOnly attribute to true. The readOnly attribute always set to true when there is no setter in the model for that property. As explained above, absence of setter should not automatically make the property readOnly - since the property can be set in the constructor during deserialisation.

Example:

Exhibit 1: The Model
(note class property "name" and json property "Name".
Valid incoming JSON: {"Name": "X", "Age": 20} )

public final class User  {

private final String name;
private final int age;

@JsonCreator
public User(@JsonProperty(value = "Name", required = true) String name,
    @JsonProperty(value = "Age", required = true) int age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}
public int getAge() {
    return age;
}

}`

Output 1: The generated swagger spec (with incorrect property name instead of Name. Also "required" attribute missing)

User:
type: "object"
properties:
	name:
		type: "string"
	age:
		type: "integer"
    	        format: "int32"

Exhibit 2: The Model (added redundant @JsonProperty on getters)

public final class User {

private final String name;
private final int age;

@JsonCreator
public User(@JsonProperty(value = "Name", required = true) String name,
    @JsonProperty(value = "Age", required = true) int age) {
    this.name = name;
    this.age = age;
}

@JsonProperty(value = "Name", required = true)
public String getName() {
    return name;
}

@JsonProperty(value = "Age", required = true)
public int getAge() {
    return age;
}

}
`
Output 2: The generated swagger spec - correct property name but now incorrectly marked as readOnly

User:
type: "object"
required:
- "Age"
- "Name"
properties:
  Name:
    type: "string"
    readOnly: true
  Age:
    type: "integer"
    format: "int32"
    readOnly: true

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions