swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.77k stars 6.02k forks source link

[Java] Definitions of Primitive Types are Generated as Objects with no accessors #3483

Open tjboudreaux opened 7 years ago

tjboudreaux commented 7 years ago
Description

In our definitions file, we have some definitions that are done for specifying constraints on primitives. Below is an example of an integer definition that we use for a Phone Number.

When doing code generation for a Java client library, this definition gets generated as a model, but there is no way to get or set it's value.

Swagger-codegen version

2.1.6

Swagger declaration file content or url
PhoneNumber:
  type: integer
  minLength: 10
  maxLength: 10
  minimum: 0

This is the generated code for this definition: https://gist.github.com/tjboudreaux/4263e3329e2239557155e0f87f6a8b0c

Command line used for generation

swagger-codegen generate -i api/swagger/swagger.json -l java -o builds/android -c

Steps to reproduce
  1. Add a definition to your swagger file that is a primitive type.
  2. Generate a java client library.
    Related issues

No related issues.

Suggest a Fix

I believe the issue is that if a definition is a primitive, it should either:

  1. generate from a model that has a property called value to store it's value
  2. or it needs to be treated as a primitive with no model class.
wing328 commented 7 years ago

@tjboudreaux thanks for reporting the issue. Is PhoneNumber defined as a property in a model?

wing328 commented 7 years ago

Btw, stable version 2.2.0 has been released. Please give it a try as it contains a lot of enhancements.

tjboudreaux commented 7 years ago

@wing328, yes it's defined as a property on multiple models. Here's one example:

OrderRestaurant:
  type: object
  required:
    - id
    - name
    - address
    - phone_number
  properties:
    id:
      type: string
    name:
      type: string
    address:
      $ref: '#/definitions/Address'
    phone_number:
      $ref: '#/definitions/PhoneNumber'

We also tried the stable version and that did not solve this specific issue.

wing328 commented 7 years ago

Swagger parser does not support that at the moment: https://github.com/swagger-api/swagger-parser/issues/243

As a workaround, please define the primitive type inline instead of using $ref

abhijith-prabhakar commented 7 years ago

Is any checkin done to fix this? Looking to see if I can use master SNAPSHOT for this

abhijith-prabhakar commented 7 years ago

A note here if and when fix is provided. If you inline primitive type and build the contract, jackson serializes it differently than having an Object property. Swagger Codegen currently generates a Java model class for primitive json(although no property is present).

mkubista commented 7 years ago

Same problem when I tried to generate Swift code with references to definition with primitive type.

wing328 commented 7 years ago

Hi all, please try the latest master (with new swagger parser), which has better support for reference to primitive type.

If there's still an issue, we'll reopen this issue.

jimvmathews commented 7 years ago

Tried this with the latest master and swagger-parser 1.028 that fixes https://github.com/swagger-api/swagger-parser/issues/243 but this issue is not resolved.

dilation commented 7 years ago

This also seems to affect the Python client generator.

dilation commented 7 years ago

However, it seems to be fixed in the latest version of the Python client generator.

wing328 commented 7 years ago

@jimvmathews did you do a mvn clean package to rebuild the JAR after pulling the latest master?

Boscop commented 7 years ago

It seems to be still not fixed in the java codegen on http://editor2.swagger.io/

wing328 commented 7 years ago

Please build the JAR based on the latest master of Swagger Codegen and see if the issue still persists.

Boscop commented 7 years ago

I mean the one that this site uses: http://editor2.swagger.io/ The admin of that site has to update it. Who is the admin?

theindexer commented 7 years ago

I just pulled and rebuilt (mvn clean package), then used swagger-codegen-cli to regenerate my java. While the useless model class doesn't exist, the code still uses it as if it did (including an import!)

Maybe I need to do something to make sure swagger-parser is up to date? I have no idea how that's getting pulled in or anything.

wing328 commented 7 years ago

@theindexer can you please provide a spec to reproduce the issue?

dentych commented 7 years ago

I have just run into this issue.

swagger: '2.0'
info:
  version: 1.0.0
  title: Number API
host: localhost
basePath: /v2
schemes:
- http
paths:
  '/numbers':
    get:
      summary: Get an array of numbers
      description: Returns an array of numbers
      operationId: getNumbers
      produces:
      - application/json
      responses:
        '200':
          description: successful operation
          schema:
            $ref: '#/definitions/Numbers'
definitions:
  Numbers:
    type: array
    items:
      $ref: '#/definitions/Number'
  Number:
    type: number

This will generate a Numbers class, which extends ArrayList - where Number is a class that doesn't exist, because it's not generated.

wing328 commented 7 years ago

@dentych what about defining the array of model response the following way instead?

https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/test/resources/2_0/petstore.yaml#L111-L117

LTheobald commented 6 years ago

Looks like I'm still getting this issue in v2.3.0-SNAPSHOT (built from the latest master) although the Java object that is incorrectly created also doesn't exist!

YAML

swagger: '2.0'
info:
  description: >-
    This is a sample server Petstore server.  You can find out more about    
    Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net,
    #swagger](http://swagger.io/irc/).      For this sample, you can use the api
    key `special-key` to test the authorization     filters.
  version: 1.0.0
  title: Swagger Petstore
  termsOfService: 'http://swagger.io/terms/'
  contact:
    email: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
host: petstore.swagger.io
basePath: /v2
schemes:
  - http
paths:
  /pet:
    get:
      summary: Return a random pet
      operationId: randomPet
      consumes:
        - application/json
      produces:
        - application/json
      responses:
        '200':
          description: A pet is returned
          schema:
            $ref: '#/definitions/PetResponse'
definitions:
  PetResponse:
    type: object
    properties:
      datetime:
        type: string
        format: datetime
        example: '2017-01-01T00:00:00Z'
      pet:
        $ref: '#/definitions/Pet'
  Pet:
    type: object
    properties:
      name:
        $ref: '#/definitions/PetName'
  PetName:
    type: string
    description: A pet`s name
    example: Mr Snuggle-Bunny

Generated class (Part of)

public class Pet   {
  @JsonProperty("name")
  private PetName name = null;

  public Pet name(PetName name) {
    this.name = name;
    return this;
  }

   /**
   * Get name
   * @return name
  **/
  @ApiModelProperty(value = "")

  @Valid

  public PetName getName() {
    return name;
  }

The class mentioned Petname hasn't been created either! Same thing happens with v2.2.3. I'd expect the Pet class to have a name property of type String.

asanikovich commented 4 years ago

opened this issue on 29 Jul 2016 - any news?