Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
pumpadump opened this issue Mar 24, 2017 · 10 comments · Fixed by #8245

Comments

@pumpadump
Copy link

pumpadump commented Mar 24, 2017

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

@cbornet
Copy link
Contributor

cbornet commented Mar 25, 2017

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

@cbornet
Copy link
Contributor

cbornet commented Mar 25, 2017

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

@pumpadump
Copy link
Author

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?

@ePaul
Copy link
Contributor

ePaul commented Mar 31, 2017

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

@Kdoki
Copy link

Kdoki commented Dec 20, 2017

Hello,

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

Regards,

@cbornet
Copy link
Contributor

cbornet commented Dec 21, 2017

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

@cbornet
Copy link
Contributor

cbornet commented Dec 21, 2017

@wing328 WDYT ?

@wing328
Copy link
Contributor

wing328 commented Jan 3, 2018

 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.

@jnovotny
Copy link

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

@fralalonde
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants