oapi-codegen icon indicating copy to clipboard operation
oapi-codegen copied to clipboard

Union tmpl generates wrong code when using non string type

Open mweibel opened this issue 1 year ago • 0 comments

openapi: "3.0.0"
info:
  version: 0.0.1
  title: Test
  description: Example
servers:
  - url: /v1

paths:
  /stuff:
    post:
      description: Create stuff
      operationId: createStuff
      security:
        - Bearer: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateStuff"
      responses:
        "201":
          description: created stuff
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Stuff"
components:
  schemas:
    CreateStuff:
      oneOf:
        - $ref: "#/components/schemas/CreateStuffBla"
        - $ref: "#/components/schemas/CreateStuffNope"
      discriminator:
        propertyName: which
        mapping:
          bla: "#/components/schemas/CreateStuffBla"
          nope: "#/components/schemas/CreateStuffNope"
    CreateStuffProperties:
      type: object
      required:
        - which
      properties:
        which:
          $ref: "#/components/schemas/WhichStuff"
    CreateStuffBla:
      allOf:
        - $ref: "#/components/schemas/CreateStuffProperties"
        - type: object
          properties:
            settings:
              $ref: "#/components/schemas/StuffBla"
    CreateStuffNope:
      allOf:
        - $ref: "#/components/schemas/CreateStuffProperties"
        - type: object
          properties:
            settings:
              $ref: "#/components/schemas/StuffNope"
    Stuff:
      type: object
      required:
        - which
      properties:
        which:
          $ref: "#/components/schemas/WhichStuff"
    WhichStuff:
      type: string
      nullable: true
      enum:
        [
          bla,
          nope,
        ]
      default: bla
    StuffBla:
      type: object
      properties:
        something:
          type: string
    StuffNope:
      type: object
      properties:
        nothing:
          type: string

generated code:

// AsCreateStuffBla returns the union data inside the CreateStuff as a CreateStuffBla
func (t CreateStuff) AsCreateStuffBla() (CreateStuffBla, error) {
	var body CreateStuffBla
	err := json.Unmarshal(t.union, &body)
	return body, err
}

// FromCreateStuffBla overwrites any union data inside the CreateStuff as the provided CreateStuffBla
func (t *CreateStuff) FromCreateStuffBla(v CreateStuffBla) error {
	v.Which = "bla"
	b, err := json.Marshal(v)
	t.union = b
	return err
}

// MergeCreateStuffBla performs a merge with any union data inside the CreateStuff, using the provided CreateStuffBla
func (t *CreateStuff) MergeCreateStuffBla(v CreateStuffBla) error {
	v.Which = "bla"
	b, err := json.Marshal(v)
	if err != nil {
		return err
	}

	merged, err := runtime.JSONMerge(t.union, b)
	t.union = merged
	return err
}

One of the errors:

'"bla"' (type string) cannot be represented by the type *WhichStuff

v.Which = "bla" (etc.) doesn't work because Which is of type *WhichStuff and not a string. In our case it's even a type within another package (i.e. using x-go-type).

Besides fixing this issue, I wonder if we could also make the generation of those From<Name> and As<Name> and Merge<Name> optional. We don't use them at all and don't plan to use them either.

This might be related to #1619 but I haven't fully verified it.

mweibel avatar Jun 24 '24 12:06 mweibel