ogen icon indicating copy to clipboard operation
ogen copied to clipboard

gen: discriminator property is removed from structures

Open johanhenriksson opened this issue 1 year ago • 1 comments

The discriminator field is removed from the generated structs. Suppose some API endpoint accepts a String and not a TypeDef and it expects to receive the kind property. Currently, the generated API client can not call such an endpoint since it wont be including the discriminator field. There could also be cases where the value of the discriminator property is useful for other things than deciding the type. Should it not always be included in the types? Especially if I manually put it as a required field like in the example below.

What version of ogen are you using?

$ go list -m github.com/ogen-go/ogen
github.com/ogen-go/ogen v0.81.0

Can this issue be reproduced with the latest version?

Yes

What did you do?

TypeDef:
  oneOf:
    - $ref: '#/components/types/String'
    - $ref: '#/components/types/Int'
  discriminator:
    propertyName: kind
    mapping:
      string: '#/components/types/String'
      int: '#/components/types/Int'

String:
  type: object
  required:
   - kind
  properties:
    kind:
      type: string
Int:
  type: object
  required:
   - kind
  properties:
    kind:
      type: string

What did you expect to see?

// Ref: #/components/types/String
type String struct{
    Kind string `json:"kind"`
}

// Ref: #/components/types/Int
type Int struct{
    Kind string `json:"kind"`
}

What did you see instead?

// Ref: #/components/types/String
type String struct{}

// Ref: #/components/types/Int
type Int struct{}

johanhenriksson avatar Jan 10 '24 17:01 johanhenriksson

@johanhenriksson did you find a workaround for this issue? The only thing I've found it to define a kind of type alias to use in oneOf schema, e.g.

StringForDiscriminator:
  allOf:
    - $ref: '#/components/types/String'
    - type: object
      properties:
         kind:
           type: string

In that case we have 2 objects generated, one to be used in the case with discriminator, and another one without. But it looks a bit ugly, tbh. Another solution is to just define a map and put data there

      additionalProperties:
        type: string

vkuptcov avatar Mar 31 '24 10:03 vkuptcov

So having following schema

openapi: 3.0.3
info:
  title: Discriminator example
  description: Example
  version: 1.0.0
paths:
    /example:
      get:
        responses:
          200:
            description: OK
            content:
              "application/json":
                schema:
                    $ref: '#/components/schemas/Response'
components:
  schemas:
    Alpha:
      type: object
      required:
        - kind
        - variant
        - data
      properties:
        kind:
          type: string
        variant:
          type: string
        data:
          type: string
    Beta:
      type: object
      required:
        - kind
        - variant
        - value
      properties:
        kind:
          type: string
        variant:
          type: string
        value:
          type: string
    SumAuto:
      oneOf:
        - $ref: '#/components/schemas/Alpha'
        - $ref: '#/components/schemas/Beta'
    SumFirst:
      discriminator:
        propertyName: kind
        mapping:
          alpha: '#/components/schemas/Alpha'
          beta: '#/components/schemas/Beta'
      oneOf:
        - $ref: '#/components/schemas/Alpha'
        - $ref: '#/components/schemas/Beta'
    SumSecond:
      discriminator:
        propertyName: variant
        mapping:
          a: '#/components/schemas/Alpha'
          b: '#/components/schemas/Beta'
      oneOf:
        - $ref: '#/components/schemas/Alpha'
        - $ref: '#/components/schemas/Beta'
    Response:
      type: object
      required:
        - Auto
        - First
        - Second
        - Alpha
        - Beta
      properties:
        Auto:
          $ref: '#/components/schemas/SumAuto'
        First:
          $ref: '#/components/schemas/SumFirst'
        Second:
          $ref: '#/components/schemas/SumSecond'
        Alpha:
          $ref: '#/components/schemas/Alpha'
        Beta:
          $ref: '#/components/schemas/Beta'

Discriminator properties are removed from Alpha and Beta, but should not.

@tdakkota please take a look.

ernado avatar Apr 11 '24 11:04 ernado

@vkuptcov I have not found a good workaround to this, no. We managed to do without it, but having the discriminator field on the generated types would make life easier.

johanhenriksson avatar Apr 11 '24 12:04 johanhenriksson