[BUG][csharp][generichost] anyOf with discriminator serializes to {}
维护者通常 1 天内回复
评估
调研方向
序列化逻辑位于 modules/openapi-generator/src/main/resources/csharp/libraries/generichost/JsonConverter.mustache 的第380-437行附近。从 AssetJsonConverter 部分的 Write 方法开始,对比 oneOf 分支(委托给子类型的 WriteProperties)和 anyOf 分支(当前写入空对象)。修复内容为让带鉴别器的 anyOf 分支也委托给映射后的子类型的写入器。通过使用提供的 schema.json 重新生成客户端,并确认包装器在往返序列化后能返回原始JSON而非 {} 来验证该更改。
由索引模型根据 Issue 内容生成。
描述
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 to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
Description
With the C# generichost generator, an anyOf wrapper with an explicit discriminator mapping reads an object into the correct subtype but serializes the wrapper as {}. Every property is lost, including the discriminator.
The concrete subtype serializes correctly using the same generated converters and serializer options. Changing only the schema composition keyword from anyOf to oneOf makes the wrapper round-trip correctly for both subtypes.
OpenAPI 3.1.1 permits a discriminator alongside anyOf: conditions for using the discriminator object.
Expected input and output:
{"type":"image","id":1,"imageUri":"https://example.com/image.jpg"}
Actual wrapper output:
{}
Verified runtime results:
| Composition | Subtype | Read / concrete subtype write | Wrapper write |
|---|---|---|---|
anyOf + discriminator |
Image | Correct | {} |
anyOf + discriminator |
Document | Correct | {} |
oneOf + discriminator |
Image | Correct | Original JSON |
oneOf + discriminator |
Document | Correct | Original JSON |
Separate scratch experiments also reproduced the failure with the generated client's own DI serializer options on the macOS host and with OpenAPI 3.0.3. Removing the discriminator in another scratch control made the anyOf wrapper round-trip both subtypes. These extra controls are not part of the checked-in runner. The actual {} output is invalid against Asset, because type is required.
openapi-generator version
- Official
openapitools/openapi-generator-cli:v7.25.0, the latest stable release checked on 2026-10-06. - .NET SDK
10.0.401, actual runtime10.0.12, Ubuntu24.04.5LTS / Linux ARM64 for generated-client execution. - Loaded
System.Text.Jsonis bundled10.0.12fromMicrosoft.NETCore.App, not a separately referenced JSON package. - The .NET orchestration uses Testcontainers
4.15.0; host macOS26.6.2/ ARM64, Docker daemon29.8.0/ Linux ARM64. - Generated-client direct packages are
Microsoft.Extensions.Http,Microsoft.Extensions.Hosting,Microsoft.Extensions.Http.PollyandMicrosoft.Net.Http.Headers, all10.0.1emitted by the stock generator.
Also reproduced on current master using openapitools/openapi-generator-cli:latest@sha256:1f59ca3f11ec33425a9c76591f261e008953644f476ada37799c595cdd1b2b65. The image reports 7.26.0-SNAPSHOT and its org.opencontainers.image.revision label matches master commit 3501c8a6684e8b4ce4c82d8c9fef7eb1f5fe91b5. A fresh scratch copy using that pinned image, with the same schema, generation settings and harness, returned the same four results and bug summary.
For the master run only, a scratch copy changed the generator image selector to accept the pinned latest@sha256:... reference above. The checked-in runner accepts released version numbers and does not support dotnet run -- latest.
I have not established which release first introduced this behavior.
OpenAPI declaration file content or url
Minimal OpenAPI 3.1.1 input: schema.json.
Asset declares anyOf with references to ImageAsset and DocumentAsset. It requires type and maps image / document discriminator values to those schemas. Each subtype requires its corresponding singleton string enum for type.
The 7.25.0 CLI validator reports No validation issues detected.
Generation Details
The .NET/Testcontainers runner executes the equivalent of:
openapi-generator-cli generate \
-i schema.json -g csharp -o generated \
--additional-properties packageName=AnyOfClient,targetFramework=net10.0,library=generichost,nullableReferenceTypes=true,hideGenerationTimestamp=true
The control copies the input and replaces anyOf with oneOf. It changes the package name to OneOfClient so both unmodified generated clients can be compiled together. There are no template overrides, modified generated files, or replacement converters.
Steps to reproduce
Requires .NET 10 and Docker with Linux containers:
git clone https://github.com/alexaka1/repro-openapitools--openapi-generator-anyof-discriminator-serialization.git
cd repro-openapitools--openapi-generator-anyof-discriminator-serialization
dotnet run
The runner generates both clients in the official generator container and executes a .NET harness in the official SDK container. For each subtype it verifies that the wrapper reader populated the subtype, that serializing the concrete subtype preserves the input, and then that serializing the wrapper preserves it.
Observed output:
SUMMARY BUG REPRODUCED: 2/2 anyOf + discriminator cases write {}; concrete subtype writes and both oneOf controls pass.
Require the SUMMARY BUG REPRODUCED line and the four RESULT lines to confirm this bug. The runner returns 1 when it reproduces with the controls passing, 0 when both wrapper compositions work, and 2 for an unexpected harness, generated-client build or control failure. Exit code 1 alone is not evidence: the host dotnet run build can also fail with 1. Docker or generator infrastructure exceptions terminate the process; the missing-image control returned 134 on this macOS host.
The runner saves generated source and logs under artifacts/, including the actual .NET environment and resolved package versions.
Related issues/PRs
- #24398 reports empty
oneOfwriters. - #23693 reports empty
oneOfwriters without a discriminator and working writes with a discriminator. - #23261 has a similar title but covers a string/null
anyOfconverter accepting and writing only objects. - Open PRs #24674 and #24735 add writers for
oneOfwithout a discriminator. Neither changes theanyOfwith discriminator path.
The reports and PRs above concern other union-writing failures. This example uses anyOf with an explicit discriminator and mapping. I did not find an exact existing report in the issue searches.
Suggest a fix
In the generated AssetJsonConverter, Write opens an object, calls an empty WriteProperties, and closes the object. In the oneOf control, Write instead delegates to the selected subtype's generated WriteProperties.
The version-specific 7.25.0 converter template supports this observed difference: the discriminator-writing branch iterates composedSchemas.oneOf, while the anyOf branch is guarded by {{^model.discriminator}}. anyOf with a discriminator reaches neither subtype-writing branch.
The same branch structure remains in the tested master source.
The discriminator path should also handle the mapped anyOf subtype. No generator patch has been tested. The oneOf control is not proposed as a general replacement for anyOf; those compositions can have different validation semantics.
- 主要语言
- Java
- 星标
- 26.8k
- 派生
- 7.7k
- 平均合并
- 1 天 15 小时
- 30 天内合并 PR
- 144
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 提供 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
OpenAPITools/openapi-generator 的其他 Issue
-
[BUG][RUST] Reqwest - encoding of spaces in path parameters可能已有人在做 @GlenWright 于 3 天前认领。 未关闭Issue: Bug
难度 2/5 1-3 小时 新手友好度 68/100
OpenAPITools/openapi-generator#25257 · 3 条评论 ·
维护者通常 1 天内回复
-
[BUG] ExampleGenerator returns the string "{}" (or null) for `type: object` schemas without `properties`可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
OpenAPITools/openapi-generator#25237 ·
维护者通常 1 天内回复
-
[BUG] OpenApiEvaluator reports "default value not in enum" for numerically equal values with different scale (e.g. 1.5 and 1.50)可能已有人在做 @mohitduhan19 于 4 天前认领。 未关闭Issue: Bug
难度 2/5 1-3 小时 新手友好度 78/100
OpenAPITools/openapi-generator#25233 ·
维护者通常 1 天内回复
-
[BUG] OpenApiEvaluator emits "Unused model" warnings even when recommendations are disabled可能已有人在做 @mohitduhan19 于 4 天前认领。 未关闭Issue: Bug
难度 2/5 1-3 小时 新手友好度 82/100
OpenAPITools/openapi-generator#25232 ·
维护者通常 1 天内回复
-
[BUG][KOTLIN] multiplatform/jvm-ktor: `DELETE` without `requestBody` sends `"Content-Type: application/json"` with an empty body可能已有人在做 @mohitduhan19 于 4 天前认领。 未关闭Issue: Bug
难度 2/5 1-3 小时 新手友好度 78/100
OpenAPITools/openapi-generator#25223 ·
维护者通常 1 天内回复
查看 OpenAPITools/openapi-generator 的全部 Issue
相似的 Issue
-
False Negative: InnerTypeLastCheck does not report members declared after inner enums or annotations未关闭
难度 2/5 1-3 小时 新手友好度 78/100
checkstyle/checkstyle#22027 ·
维护者通常 1 天内回复
-
bug follow-up lane:auto
难度 2/5 1-3 小时 新手友好度 85/100
Sanne/incus-spawn#1497 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
维护者通常 1 天内回复
-
[CI] NettyClientTest.testServerDisconnection may fail with DisconnectException可能已有人在做 @yangshangqing95 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 86/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100