OpenAPITools / OpenAPITools/openapi-generator

[BUG][Go] No json tags emitted when a schema has both properties and a schema-level oneOf, silently dropping snake_case fields on decode

Open
#24,916 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master? — tested with the latest release, v7.25.0
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
Description

When a schema declares properties and a schema-level oneOf, the Go generator emits the model struct with no json tags at all. Go's decoder then falls back to matching field names case-insensitively, and that fallback does not ignore underscores — so every property whose wire name contains one is silently dropped on decode, while single-word properties decode fine.

This is worse than a cosmetic tag issue:

  • MarshalJSON is generated from a hand-built ToMap() that keeps the correct snake_case keys, so serialization stays healthy. Only deserialization loses data, and only for some fields.
  • The generated UnmarshalJSON deletes the known keys from AdditionalProperties, so the value is not recoverable there either.
  • Tests that construct the model in Go and assert on its fields never touch the tags, so they stay green while decoding is broken. The failure surfaces only against a real payload.

The oneOf involved need not define variants. In the repro it is a pure co-occurrence constraint — "either first_value or second_value, not both" — which adds no shape and which the Go generator cannot express in the type system either way. It is valid OpenAPI, and it is the natural way to describe a schema that has gained a second mutually exclusive encoding, yet its mere presence costs the schema every tag.

openapi-generator version

7.25.0. Also reproduced on 7.18.0, so this is not a recent regression.

OpenAPI declaration file content
openapi: 3.0.3
info:
  title: Tag Loss Repro
  version: 1.0.0
paths:
  /thing:
    get:
      operationId: getThing
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Thing'
components:
  schemas:
    Thing:
      type: object
      required: [kind]
      properties:
        kind:
          type: string
        first_value:
          type: array
          items:
            type: number
        second_value:
          type: array
          items:
            type: number
      oneOf:
        - required: [first_value]
          not:
            required: [second_value]
        - required: [second_value]
          not:
            required: [first_value]
Generation details
docker run --rm -v "$PWD:/local" openapitools/openapi-generator-cli:v7.25.0 generate \
  -i /local/spec.yaml -g go -o /local/out \
  --additional-properties="withGoMod=false,packageName=client"

Actual

type Thing struct {
	Kind string
	FirstValue []float32
	SecondValue []float32
}

Expected — and exactly what the generator produces from the same spec with the oneOf block removed, which isolates the trigger:

type Thing struct {
	Kind string `json:"kind"`
	FirstValue []float32 `json:"first_value,omitempty"`
	SecondValue []float32 `json:"second_value,omitempty"`
}

With the oneOf present, json.Unmarshal of {"kind":"example","first_value":[1,2],"second_value":[3,4]} leaves both slices empty while Kind is populated.

Related

#21461 reports missing omitempty on the members of a pure oneOf union. Possibly the same code path classifying any schema carrying oneOf as a union model, but the symptom and blast radius differ: that one loses an omitempty on a wrapper, this one loses every tag on an ordinary model and drops data.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with spec.yaml and reproduce the issue using the documented Docker command and Go generator, then trace how schemas containing both properties and oneOf are classified. Done means generated models retain their json tags and a real json.Unmarshal regression case preserves first_value and second_value.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, openapi
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.