Skip to content

Nested nullable unions silently discard JSON payloads #2565

Description

@g-logunov

An OpenAPI 3.1 nullable wrapper around an inline oneOf or anyOf generates a union struct without its JSON methods. Generation succeeds, but unmarshalling and then marshalling silently drops the union payload.

Reproduced on main at 833a968f84b4b0ec7c2f3fb5bb119e3c449f7a4f, using Go 1.27.1 on darwin/arm64, with compatibility.schema-merging-behavior set to v1, v2, or v3.

Reproduction

Save these three files in a new directory. The reproduction is provided under Apache-2.0.

spec.yaml:

openapi: 3.1.0
info:
  title: Nested nullable union reproduction
  version: 1.0.0
paths: {}
components:
  schemas:
    Envelope:
      type: object
      required: [pet]
      properties:
        pet:
          anyOf:
            - oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
            - type: 'null'
    Cat:
      type: object
      required: [meow]
      properties:
        meow: {type: string}
    Dog:
      type: object
      required: [bark]
      properties:
        bark: {type: string}

config.yaml:

package: repro
output: types.gen.go
generate:
  models: true
output-options:
  skip-prune: true

repro_test.go:

package repro

import (
	"encoding/json"
	"testing"
)

func TestNestedNullableUnionRoundTrip(t *testing.T) {
	const input = `{"pet":{"meow":"purr"}}`
	var value Envelope
	if err := json.Unmarshal([]byte(input), &value); err != nil {
		t.Fatal(err)
	}
	output, err := json.Marshal(value)
	if err != nil {
		t.Fatal(err)
	}
	if string(output) != input {
		t.Fatalf("got %s, want %s", output, input)
	}
}

Run:

go mod init example.com/nested-nullable-repro
go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@833a968f84b4b0ec7c2f3fb5bb119e3c449f7a4f --config=config.yaml spec.yaml
go get github.com/oapi-codegen/[email protected]
go test .

Actual result:

got {"pet":{}}, want {"pet":{"meow":"purr"}}

Expected: the complete payload survives the JSON round trip.

Cause

The nullable-union collapse path drops UnionElements and Discriminator, so the union's JSON methods and accessors are not generated.

Related to #2218. This reproduces after the OpenAPI 3.1 support added in #2336.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions