Swagger-codegen: [Java] doesnt generate correct classes for models with same nested properties

Created on 1 Mar 2017  路  13Comments  路  Source: swagger-api/swagger-codegen

Description

If there are two models in the swagger definition whose subproperties are the same, the code generator always uses the first one.

e.g. take the following two definitions

  house:
    type: object
    properties:
      has_walls:
        type: boolean
      attributes:
        type: object
        properties:
          name:
            type: string

  person:
    type: object
    properties:
      has_legs:
        type: boolean
      attributes:
        type: object
        properties:
          name:
            type: string

Swagger doesnt generate a PersonAttributes class at all, and instead generates:

public class Person   {
  @JsonProperty("has_legs")
  private Boolean hasLegs = null;

  @JsonProperty("attributes")
  private HouseAttributes attributes = null;
Swagger-codegen version

Latest snapshot 2.2.2

Swagger declaration file content or url
swagger: '2.0'
info:
  version: 0.0.0
  title: Simple API
paths:
  /:
    get:
      responses:
        200:
          description: OK
          schema:
            $ref: "#/definitions/house"
        400:
          description: OK
          schema:
            $ref: "#/definitions/person"

definitions:

  house:
    type: object
    properties:
      has_walls:
        type: boolean
      attributes:
        type: object
        properties:
          name:
            type: string

  person:
    type: object
    properties:
      has_legs:
        type: boolean
      attributes:
        type: object
        properties:
          name:
            type: string

Command line used for generation

java -jar bin/swagger-codegen-cli.jar generate -v -i ./swagger.yaml -l spring -Dmodels -o .

Steps to reproduce

Copy the above swagger.yaml into http://editor.swagger.io/#!/ or use the latest CLI to build as above.

Java Question

Most helpful comment

IMHO I would personally not go for the shared models at all. If the developer wants to generate shared models, its simple for them to go through the swagger definition and separate out the models in whatever way they want. They will have a much better understanding of what can and cannot logically be shared that you can get from automated parsing. I'd just suggest a simple rule that anything thats defined in a top level 'definition' would be logically separate, and I think that would be the most easily understandable and consistent.

All 13 comments

On second thoughts this might be a parser error, since I've tried generating a few other types of servers and they all have the same issue (e.g. ASPNET, Flask).

@wing328 any idea where the issue might lie?

@stevecookform3 I think that's because you're defining the model inline and swagger codegen will try to generate only 1 model if both inline models appear to be the same.

You can try to add the title attribute to have a better control on the naming of the inline object or try to define the model separately instead of inline.

@wing328 where would the title attribute go? In the spec I can only see the title attribute used as the title of the app, not at individual model levels (title: "Swagger Sample App")..

Something like this:

      attributes:
        title: NewNameHere
        type: object
        properties:
          name:
            type: string

I would recommend defining the model separately instead of inline.

@wing328 thanks for the info. FYI adding the title attribute doesnt make any difference - the model is still not generated.

Using a ref does work as a workaround for the issue though, so the following will generate the correct code:

definitions:

  house:
    type: object
    properties:
      has_walls:
        type: boolean
      attributes:
        $ref: "#/definitions/houseattributes"

   houseattributes:
        type: object
        properties:
          name:
            type: string

  person:
    type: object
    properties:
      has_legs:
        type: boolean
      attributes:
        $ref: "#/definitions/personattributes"

  personattributes:
        type: object
        properties:
          name:
            type: string

However i'm not sure this is great for a couple of reasons:

  • The whole model is not the same, only a sub-part of it. Its therefore confusing to have some of the model created using subparts of a different model. Its also difficult to anticipate which objects are going to be shared and which aren't.
  • The workaround is more verbose, and more difficult to read

Is there any simple way to disable this behaviour in the codegen, or any plans to change the default to not try to create semi-shared models?

Understood that different developers have different preferences on how to define models.

What about disabling the behaviour if the "title" attribute is present?

IMHO I would personally not go for the shared models at all. If the developer wants to generate shared models, its simple for them to go through the swagger definition and separate out the models in whatever way they want. They will have a much better understanding of what can and cannot logically be shared that you can get from automated parsing. I'd just suggest a simple rule that anything thats defined in a top level 'definition' would be logically separate, and I think that would be the most easily understandable and consistent.

I've been hitting this issue as well. I thought it would get into the 2.2.3 release, why has it been postponed? Is there any chance this will get into a release soon?
Cheers!

@tanis2000 please use the workaround as we've not decided on the "correct" behaviour:

Using a ref does work as a workaround for the issue though, so the following will generate the correct code:

@wing328 thanks for the follow up. I am indeed using a ref for the time being. It's just that avoiding to add refs everywhere would make things easier. Thanks for the great work anyway! :)

@stevecookform3
@tanis2000
I know this is old but I've been hitting the very same issue and this thread has helped a lot in my research. I will create a pull request for a new setting in the Maven plugin when/if I get a green light for a corresponding swagger-parser issue as this is a dependency here.

@xnsdns this change would definitely be helpful in future projects as well.

Was this page helpful?
0 / 5 - 0 ratings