swagger-api / swagger-api/swagger-codegen
[JAVA] The java code generated for properties starting with two uppercase letters leads creates wrong json.
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
If the swagger declaration contains properties with names starting with two uppercase letters, the generated java code is not java bean conform. As a result jackson maps the properties twice.
See: http://futuretask.blogspot.de/2005/01/java-tip-6-dont-capitalize-first-two.html
Swagger-codegen version
Tested with 2.2.1 and 2.2.2-SNAPSHOT
Swagger declaration file content or url
swagger: '2.0'
schemes:
- http
basePath: '/v0.1/foo'
consumes:
- 'application/json'
produces:
- 'application/json'
paths:
'/foo':
get:
responses:
200:
description: "successful operation"
schema:
type: "array"
items:
$ref: "#/definitions/Pet"
definitions:
Pet:
description: >
Pet
type: object
properties:
ATT_Name:
description: >
Name of the pet
type: string
generated java code:
/**
* Pet
*/
@ApiModel(description = "Pet ")
@javax.annotation.Generated(value = "class io.swagger.codegen.languages.JavaClientCodegen", date = "2016-10-22T10:58:27.662+02:00")
public class Pet {
@JsonProperty("ATT_Name")
private String aTTName = null;
public Pet aTTName(String aTTName) {
this.aTTName = aTTName;
return this;
}
/**
* Name of the pet
* @return aTTName
**/
@ApiModelProperty(example = "null", value = "Name of the pet ")
public String getATTName() {
return aTTName;
}
public void setATTName(String aTTName) {
this.aTTName = aTTName;
}
@Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pet pet = (Pet) o;
return Objects.equals(this.aTTName, pet.aTTName);
}
@Override
public int hashCode() {
return Objects.hash(aTTName);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Pet {\n");
sb.append(" aTTName: ").append(toIndentedString(aTTName)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(java.lang.Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
jackson serialization result:
{"attname":"cat","ATT_Name":"cat"}
Command line used for generation
swagger-codegen-maven-plugin
Steps to reproduce
Build a jaxrs or spring server. Implement controller to return Pet array.
Or use jackson mapper and serialize with the generated Pet model code.
Related issues
https://github.com/swagger-api/swagger-codegen/issues/445
Suggest a Fix
DefaultCodegen.java:
/**
* Camelize name (parameter, property, method, etc)
*
* @param word string to be camelize
* @param lowercaseFirstLetter lower case for first letter if set to true
* @return camelized string
*/
public static String camelize(String word, boolean lowercaseFirstLetter) {
if(lowercaseFirstLetter) {
if(startsWithTwoUppercaseLetters(word)){
word = word.substring(0, 2).toLowerCase() + word.substring(2);
}
}
// Replace all slashes with dots (package separator)
Pattern p = Pattern.compile("\\/(.?)");
Matcher m = p.matcher(word);
while (m.find()) {
word = m.replaceFirst("." + m.group(1)/*.toUpperCase()*/); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
m = p.matcher(word);
}
// case out dots
String[] parts = word.split("\\.");
StringBuilder f = new StringBuilder();
for (String z : parts) {
if (z.length() > 0) {
f.append(Character.toUpperCase(z.charAt(0))).append(z.substring(1));
}
}
word = f.toString();
m = p.matcher(word);
while (m.find()) {
word = m.replaceFirst("" + Character.toUpperCase(m.group(1).charAt(0)) + m.group(1).substring(1)/*.toUpperCase()*/);
m = p.matcher(word);
}
// Uppercase the class name.
p = Pattern.compile("(\\.?)(\\w)([^\\.]*)$");
m = p.matcher(word);
if (m.find()) {
String rep = m.group(1) + m.group(2).toUpperCase() + m.group(3);
rep = rep.replaceAll("\\$", "\\\\\\$");
word = m.replaceAll(rep);
}
// Remove all underscores
p = Pattern.compile("(_)(.)");
m = p.matcher(word);
while (m.find()) {
word = m.replaceFirst(m.group(2).toUpperCase());
m = p.matcher(word);
}
if (lowercaseFirstLetter) {
word = word.substring(0, 1).toLowerCase() + word.substring(1);
}
return word;
}
private static boolean startsWithTwoUppercaseLetters(String word) {
boolean startsWithTwoUppercaseLetters = false;
if(word.length() > 1) {
startsWithTwoUppercaseLetters = word.substring(0, 2).equals(word.substring(0, 2).toUpperCase());
}
return startsWithTwoUppercaseLetters;
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read DefaultCodegen.java, especially camelize and startsWithTwoUppercaseLetters, then reproduce the issue with the provided Swagger declaration and generated Pet model. Done means properties beginning with two uppercase letters produce JavaBean-conformant accessors and Jackson serializes the property only once.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100