Bug Report Checklist
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.
Bug Report Checklist
Description
When a schema declares
propertiesand a schema-leveloneOf, the Go generator emits the model struct with nojsontags 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:
MarshalJSONis generated from a hand-builtToMap()that keeps the correct snake_case keys, so serialization stays healthy. Only deserialization loses data, and only for some fields.UnmarshalJSONdeletes the known keys fromAdditionalProperties, so the value is not recoverable there either.The
oneOfinvolved need not define variants. In the repro it is a pure co-occurrence constraint — "eitherfirst_valueorsecond_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
Generation details
Actual
Expected — and exactly what the generator produces from the same spec with the
oneOfblock removed, which isolates the trigger:With the
oneOfpresent,json.Unmarshalof{"kind":"example","first_value":[1,2],"second_value":[3,4]}leaves both slices empty whileKindis populated.Related
#21461 reports missing
omitemptyon the members of a pureoneOfunion. Possibly the same code path classifying any schema carryingoneOfas a union model, but the symptom and blast radius differ: that one loses anomitemptyon a wrapper, this one loses every tag on an ordinary model and drops data.