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
For immutable model classes (no setters), which are deserialised from json using @JsonCreator annotation on constructor, the translation goes wrong in following ways:
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})}`
Output 1: The generated swagger spec (with incorrect property name instead of Name. Also "required" attribute missing)
Exhibit 2: The Model (added redundant @JsonProperty on getters)
}
`
Output 2: The generated swagger spec - correct property name but now incorrectly marked as readOnly