PolymorphExtensions.System.Text.Json 1.0.2

dotnet add package PolymorphExtensions.System.Text.Json --version 1.0.2
NuGet\Install-Package PolymorphExtensions.System.Text.Json -Version 1.0.2
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PolymorphExtensions.System.Text.Json" Version="1.0.2" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add PolymorphExtensions.System.Text.Json --version 1.0.2
#r "nuget: PolymorphExtensions.System.Text.Json, 1.0.2"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install PolymorphExtensions.System.Text.Json as a Cake Addin
#addin nuget:?package=PolymorphExtensions.System.Text.Json&version=1.0.2

// Install PolymorphExtensions.System.Text.Json as a Cake Tool
#tool nuget:?package=PolymorphExtensions.System.Text.Json&version=1.0.2

Polymorph extensions for System.Text.Json

This library contains utilities for serializing and deserializing subclasses of type hierarchies, while keeping type information and also keeping your model free from discriminator properties. The library uses a set of Attributes to achiveve this. You can customize the name of the discriminator property in the generated JSON string and also the values for the discriminator properties for each subclass.

The customization of the discriminator property values lets you create meaningful discriminator values that you can easily use in your client that was not created with .NET.

Usage

Configuring type hierarchy

Let's say you have a class hiearchy like this:

public class BaseDto
{
    public int BaseDtoProperty { get; set; }
}

public class SubDto1 : BaseDto
{
    public string SubDtoProperty1 { get; set; }
}

public class SubDto2 : BaseDto
{
    public long SubDtoProperty2 { get; set; }
}

public class SubDto3 : BaseDto
{
    public bool SubDtoProperty3 { get; set; }
}

You can add the attributes defined in the library, to set up serialization:

// DiscriminatorPropertyName is optional, it defaults to "discriminator"
[JsonBaseClass(DiscriminatorName = "myAwesomeDiscriminator")]
public class BaseDto
{
    public int BaseDtoProperty { get; set; }
}

// DiscriminatorName is optional, it defaults to the name of the subclass.
// You can omit it if you use a .NET Client and have the concrete types
// Or if you simply don't mind having class names as discriminators
[JsonSubClass(DiscriminatorValue = "Sub1")]
public class SubDto1 : BaseDto
{
    public string SubDtoProperty1 { get; set; }
}

[JsonSubClass(DiscriminatorValue = "Sub2")]
public class SubDto2 : BaseDto
{
    public long SubDtoProperty2 { get; set; }
}

[JsonSubClass]
public class SubDto3 : BaseDto
{
    public bool SubDtoProperty3 { get; set; }
}

Configuring the serialization with ASP.NET Core

If you are using ASP.NET Core, you can add your type hierarchies via reflection at the ConfigureServices method:

services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.AddDiscriminatorConverters(
            Assembly.Load("Your.Assembly.Containing.The.Classes"),
            Assembly.Load("An.Other.Assembly.Containing.Classes")
        );
    });

If you don't want the library to detect your hierarchies with reflection, you can use the following extension method:

services.AddControllers()
    .AddJsonOptions(options =>
    {
        // In this case you don't need to place the JsonBaseClassAttribute on your BaseDto
        // You might need to specifiy the assemblies where your subclasses were declared
        // The libary will look for subclasses in the same Assembly as the BaseDto
        options.JsonSerializerOptions.AddDiscriminatorConverterForHierarchy<BaseDto>("myAwesomeDiscriminator");
    });

And you are done. The following example will show how to use this in Controllers:

[Route("discriminator-test")]
[ApiController]
public class DiscriminatorTestController : ControllerBase
{
    [HttpGet]
    public BaseDto Get()
    {
        return new SubDto2 { BaseDtoProperty = 0, SubDtoProperty2 = 1 };
    }
    
    [HttpPost]
    public void Post(BaseDto dto)
    {
        if (dto is SubDto1 subDto)
        {
            Console.WriteLine(subDto.SubDtoProperty1);
        }
    }
}

If we send a GET request to this Controller we will get the following response:

{
  "myAwesomeDiscriminator": "Sub2",
  "baseDtoProperty": 0,
  "subDtoProperty2": 1
}

If we send a POST request to this controller, with the content below, it is going to log foo to the console:

{
  "myAwesomeDiscriminator": "Sub1",
  "baseDtoProperty": 1,
  "subDtoProperty1": "foo"
}

Configuring the serialization

If you are using the JsonSerializer class for serializing and deserializing your classes, you can call either the AddDiscriminatorConverters or the AddDiscriminatorConverterForHierarchy<> extension method to add your converters, like in the example with ASP.NET Core.

var dto = ...;
var options = new JsonSerializerOptions();
options.AddDiscriminatorConverters(
    Assembly.Load("Your.Assembly.Containing.The.Classes"),
    Assembly.Load("An.Other.Assembly.Containing.Classes")
);

var json = JsonSerializer.Serialize(dto, options);
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net5.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.2 465 4/25/2021
1.0.1 352 4/25/2021
1.0.0 291 4/25/2021