[BUG][Go] No json tags emitted when a schema has both properties and a schema-level oneOf, silently dropping snake_case fields on decode
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:
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.- The generated
UnmarshalJSONdeletes the known keys fromAdditionalProperties, 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.
Source: OpenAPITools/openapi-generator