Skip to content

[JAVA] The java code generated for properties starting with two uppercase letters leads creates wrong json. #4051

@schnabel

Description

@schnabel
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

#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;
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions