Swagger-codegen: [JAVA][SPRING] Swagger codegen generates wrong java object for json objects with additional properties

Created on 24 Mar 2017  路  10Comments  路  Source: swagger-api/swagger-codegen

Description

Swagger Codegen generates a java model object that extends HashMap for json objects that have the additionalProperties: property set. This leads to jackson only serealizing the properties added to the hashmap and ignoring all additional properties that are set explicitly in the java file.

Swagger-codegen version

2.2.2

Swagger declaration file content or url
 Datavalue:
    type: object
    description: The individual dataelements 
    required:
      - id
    properties:
      id:
        type: string
      source:
        type: string
      target:
        type: string
    additionalProperties:
      type: string

This generates a model object that starts like this:

public class Datavalue extends HashMap<String, String>  {
  @JsonProperty("id")
  private String id = null;

  @JsonProperty("source")
  private String source = null;

  @JsonProperty("target")
  private String target = null;

  public Datavalue id(String id) {
    this.id = id;
    return this;
  }

Serializing this objects leads to a json that is missing the explicitly set properties (id, source, target).
http://stackoverflow.com/questions/31320983/jackson-serialise-map-with-extra-fields

I think instead it should generate a java object that has a hashmap as a variable and the following annotated getter and setter methods, similar to this:

public class Datavalue   {
  @JsonProperty("id")
  private String id = null;

  @JsonProperty("source")
  private String source = null;

  @JsonProperty("target")
  private String target = null;

  protected Map<String,String> otherProperties = new HashMap<String,String>();

  public Datavalue id(String id) {
    this.id = id;
    return this;
  }
  @JsonAnyGetter
  public Map<String, String> any() {
   return this.otherProperties;
  }

  @JsonAnySetter
  public void set(String name, String value) {
   this.otherProperties.put(name, value);
  }

as Explained here: http://www.cowtowncoder.com/blog/archives/2011/07/entry_458.html

Java Bug Spring

Most helpful comment

Yes, seems better. Would you do the PR ? Maybe against 2.3.0 branch since it's a breaking change.
Also additionalProperties would be better than otherProperties for the field name

All 10 comments

Yes, seems better. Would you do the PR ? Maybe against 2.3.0 branch since it's a breaking change.
Also additionalProperties would be better than otherProperties for the field name

And ideally that would be done for all Java based codegens.

Ok i will try to figure out where to add such changes and create a PR. Can you point me to a good starting point?

@pumpadump
I think one starting point would be src/main/resources/Java/pojo.mustache.

There we see

public class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{{#parcelableModel}}implements Parcelable {{#serializableModel}}, Serializable {{/serializableModel}}{{/parcelableModel}}{{^parcelableModel}}{{#serializableModel}}implements Serializable {{/serializableModel}}{{/parcelableModel}}{

... the extends logic thus comes from the existence of a parent item in the CodegenModel object.

Somewhere in DefaultCodegen or AbstractJavaCodegen this likely is done.

Hello,

Is there any news about this issue ? or a workaround ?

Regards,

There are several things to consider here:

  • what should we do if there is only additionalProperties and no properties ? Keep the HashMap inheritance or add the JsonAnyGetter/JsonAnySetter ?
  • this will not work with gson. Not a problem for Spring codegen but it could be one for the java client ones.

Note : to change the behavior, override the addAdditionPropertiesToCodeGenModel method and fill the additionalPropertiesType property

@wing328 WDYT ?

 Datavalue:
    type: object
    description: The individual dataelements 
    required:
      - id
    properties:
      id:
        type: string
      source:
        type: string
      target:
        type: string
    additionalProperties:
      type: string

@pumpadump what does the JSON payload looks like? I want to ensure it's defined correctly.

Any news on this? I had to hand hack my class.. doesn't include the required param in the hashmap

I just hit this issue. I think the @JsonAnyGetter solution would fit the bill perfectly.

A first step could be to flag-enable this new way of doing things so that default behavior forgson compatibility is maintained.

I would add a requirement to allow accessing the dynamic properties map directly.

Was this page helpful?
0 / 5 - 0 ratings