C# oneOf deserialization silently loses data when no discriminator is defined
- Dominant language
- C#
- Stars
- 3.8k
- Forks
- 333
- Avg merge
- 16h 29m
- Merged PRs (30d)
- 116
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:
```yaml
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:
```json
{
"effectType": "addLoyaltyPoints",
"props": {
"name": "Product registered",
"value": 75,
"programId": 37,
"transactionUUID": "abc-123"
}
}
```
After Kiota deserialization:
```csharp
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
Contributor guide
Assessment
This issue has not been assessed yet.