Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[BUG][csharp][generichost] anyOf with discriminator serializes to {}

オープン 初心者向け
#25,154 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
75/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
csharp
領域
tooling

調査の方向性

シリアライズロジックは 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 runtime 10.0.12, Ubuntu 24.04.5 LTS / Linux ARM64 for generated-client execution.
  • Loaded System.Text.Json is bundled 10.0.12 from Microsoft.NETCore.App, not a separately referenced JSON package.
  • The .NET orchestration uses Testcontainers 4.15.0; host macOS 26.6.2 / ARM64, Docker daemon 29.8.0 / Linux ARM64.
  • Generated-client direct packages are Microsoft.Extensions.Http, Microsoft.Extensions.Hosting, Microsoft.Extensions.Http.Polly and Microsoft.Net.Http.Headers, all 10.0.1 emitted 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 oneOf writers.
  • #23693 reports empty oneOf writers without a discriminator and working writes with a discriminator.
  • #23261 has a similar title but covers a string/null anyOf converter accepting and writing only objects.
  • Open PRs #24674 and #24735 add writers for oneOf without a discriminator. Neither changes the anyOf with 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
平均マージ
2日 7時間
マージ済み PR(30日)
148

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

OpenAPITools/openapi-generator のほかの issue

OpenAPITools/openapi-generator の issue をすべて見る

似ている issue

Java の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。