Skip to content

C# oneOf deserialization silently loses data when no discriminator is defined #7573

Description

Description

When an OpenAPI spec defines a oneOf composed type without a discriminator, Kiota generates an IComposedTypeWrapper class with properties for each concrete type. At runtime, deserialization silently produces null values for all typed properties -- the JSON data is effectively lost.

Steps to reproduce

OpenAPI spec:

Effect:
  allOf:
    - \$ref: '#/components/schemas/EffectEntity'
    - type: object
      properties:
        props:
          oneOf:
            - \$ref: '#/components/schemas/AddLoyaltyPointsEffectProps'
            - \$ref: '#/components/schemas/DeductLoyaltyPointsEffectProps'
            - \$ref: '#/components/schemas/TriggerWebhookEffectProps'
            # ... ~30 more types

The JSON response from the API:

{
  "effectType": "addLoyaltyPoints",
  "props": {
    "name": "Product registered",
    "value": 75,
    "programId": 37,
    "transactionUUID": "abc-123"
  }
}

After Kiota deserialization:

effect.Props                              // not null (Effect_props wrapper)
effect.Props.AddLoyaltyPointsEffectProps  // null
effect.Props.DeductLoyaltyPointsEffectProps // null
// All typed properties are null -- data is lost
// AdditionalData on Effect_props is not available (IComposedTypeWrapper doesn't implement IAdditionalDataHolder)

Expected behavior

At minimum, one of:

  1. The data should be preserved in AdditionalData on the composed type wrapper so consumers can access it
  2. Kiota should attempt to populate all concrete types with matching fields (best-effort deserialization)
  3. A warning should be emitted at generation time that oneOf without discriminator will not deserialize correctly in C#

Actual behavior

All typed properties on the IComposedTypeWrapper are null. The JSON data is silently discarded with no error, warning, or fallback. There is no way to access the original data.

Workaround

We replaced the oneOf with a single flat schema containing all fields as optional properties, then regenerated the client. This works but loses the type safety that oneOf is meant to provide.

Environment

  • Kiota version: 1.29.0
  • Language: C#
  • .NET version: 9.0

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

Status
Needs Triage 🔍

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions