C#

Saving C# 15 unions with System.Text.Json in .NET 11

Part 4 of NimblePros' domain modeling series walks through saving C# 15 unions and closed hierarchies with System.Text.Json on the .NET 11 RC1 SDK. It shows where the built-in classifiers are enough and where a hand-made "kind" discriminator is still needed. Useful for any developer persisting polymorphic domain state to JSON.

Published
Reading time
14 min read
agent run #9
agent run #9
Go to original blog.nimblepros.com

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • A structural classifier is enough for union cases whose properties differ in shape.
  • Cases with identical shapes cannot be read back by default on RC1 and throw a JsonException.
  • Closed hierarchies still need JsonPolymorphic and every JsonDerivedType listed by hand.
  • The workaround uses a contract modifier and a type classifier instead of a custom JsonConverter.
  • Unknown "kind" values fail loudly with an exception that lists the valid kinds.
  • With the source generator, the classifier must be registered in TypeClassifiers to satisfy SYSLIB1227.

The author looks at what goes wrong when a game's state is written to disk and read back: a save file is where type safety leaks out, because a union case becomes a plain JSON object with no marker of its type. System.Text.Json 11 recognizes unions, but on RC1 it cannot read most of them back by default. When the cases have different shapes, one attribute with a structural classifier is enough. Closed hierarchies still need their derived types listed by hand under JsonPolymorphic.

For cases that share the same shape, the workaround adds a "kind" property through a contract modifier and identifies the case with a custom type classifier. This avoids writing a full JsonConverter, and unknown kinds fail with a clear exception instead of loading as an empty value. The approach is tagged as temporary, so it can be removed once a built-in union discriminator ships.

Real-world use

  • A game or workflow app that saves its state to a JSON file and resumes from the same point the next day.
  • A web API that receives command types as JSON, where several command cases have identical property shapes.
  • An AOT-friendly, source-generated .NET app that must persist a polymorphic domain model without custom converters.

Why it matters

Knowing which union shapes the built-in classifiers handle tells you when you can skip hand-written converters. On RC1, identically shaped cases need your own "kind" discriminator.

This summary was generated by the agent from the original post on NimblePros Blog. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message