using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Text.Json.Serialization;
public string Name { get; set; }
public class Customer : Person
public decimal CreditLimit { get; set; }
public class Employee : Person
public string OfficeNumber { get; set; }
public class PersonConverterWithTypeDiscriminator : JsonConverter<Person>
public override bool CanConvert(Type typeToConvert) =>
typeof(Person).IsAssignableFrom(typeToConvert);
public override Person Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException();
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException();
string propertyName = reader.GetString();
if (propertyName != "TypeDiscriminator")
throw new JsonException();
if (reader.TokenType != JsonTokenType.Number)
throw new JsonException();
TypeDiscriminator typeDiscriminator = (TypeDiscriminator)reader.GetInt32();
Person person = typeDiscriminator switch
TypeDiscriminator.Customer => new Customer(),
TypeDiscriminator.Employee => new Employee(),
_ => throw new JsonException()
if (reader.TokenType == JsonTokenType.EndObject)
if (reader.TokenType == JsonTokenType.PropertyName)
propertyName = reader.GetString();
decimal creditLimit = reader.GetDecimal();
((Customer)person).CreditLimit = creditLimit;
string officeNumber = reader.GetString();
((Employee)person).OfficeNumber = officeNumber;
string name = reader.GetString();
throw new JsonException();
public override void Write(
Utf8JsonWriter writer, Person person, JsonSerializerOptions options)
writer.WriteStartObject();
if (person is Customer customer)
writer.WriteNumber("TypeDiscriminator", (int)TypeDiscriminator.Customer);
writer.WriteNumber("CreditLimit", customer.CreditLimit);
else if (person is Employee employee)
writer.WriteNumber("TypeDiscriminator", (int)TypeDiscriminator.Employee);
writer.WriteString("OfficeNumber", employee.OfficeNumber);
writer.WriteString("Name", person.Name);
public static void Test()
var options = new JsonSerializerOptions
Converters = { new PersonConverterWithTypeDiscriminator() },
var json = @"{""TypeDiscriminator"":2,""OfficeNumber"":""1-111-111-1111"",""Name"":""my name"", ""ExtraData"" : {""Value"" : ""extra value""} }";
var person = JsonSerializer.Deserialize<Person>(json, options);
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];