Skip to content

Missing discriminator mapping gives StackOverflowException when generating C# clients using System.Text.Json #4375

@jeremia

Description

@jeremia

This applies to:

  • NSwagStudio
  • Generation of a C# client
  • Using System.Text.Json
  • Polymorphic deserialization
  • Missing mapping for discriminator

The problem

When a discriminator with mapping exists on a base type and the sub type schemas has an allOf reference to the base schema NswagStudio creates a nice JsonInheritanceConverter to handle the polymorphic serialization/deserialization.
It finds the correct sub class and deserialize to that subclass.
For System.Text.Json it looks like this.
return (TBase)System.Text.Json.JsonSerializer.Deserialize(bufferWriter.ToArray(), subtype, options);

That is all good.
The problem is when the discriminator has a value with no defined mapping.
In that case the the JsonInheritanceConverter concludes that the "subtype" is the basetype.
That makes the call to Deserialize point to the JsonInheritanceConverter again which creates an eternal loop, which gives a StackOverflowException.
return (TBase)System.Text.Json.JsonSerializer.Deserialize(bufferWriter.ToArray(), subtype, options);

When using Newtonsoft a missing mapping results in deserializing to the base class, which is the behavior I would like.

Possible solutions

There are not any good solutions pre .NET 7.

.NET 7 solution

In .NET 7 polymorphic serialization and deserialization are supported by the framework without any custom converters using JsonDerivedTypeAttribute and JsonPolymorphicAttribute. It seems like a missing mapping when using JsonDerivedTypeAttribute results in deserializing to the BaseClass by default. If any problems there is a setting for this in JsonPolymorphicAttribute.IgnoreUnrecognizedTypeDiscriminators.

Pre .NET 7 solutions

  • A subclass with no additional properties could be generated and missing mappings could be deserialzed to this subclass.
  • You could manually deserialize each property of the base class.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions