using Newtonsoft.Json.Serialization;
using System.Collections.Generic;
public static void Main()
JsonConvert.DefaultSettings = () => {
return new JsonSerializerSettings() {
ContractResolver = new DefaultContractResolver() {
NamingStrategy = new SnakeCaseNamingStrategy()
Converters = new List<JsonConverter>() {
JsonSubtypesConverterBuilder.Of(typeof(ItemBase), "type")
.RegisterSubtype(typeof(ItemDerived1), "A")
.RegisterSubtype(typeof(ItemDerived2), "B")
.RegisterSubtype(typeof(SubItems), "sub")
""name"": ""container1"",
""base_prop_str"": ""example1"",
""prop_deriv_a"": ""derived1""
""base_prop_str"": ""example2"",
""base_prop_str"": ""example3"",
""base_prop_str"": ""example4""
c = JsonConvert.DeserializeObject<Container>(json);
Console.WriteLine($"Error while deserializing: {e.Message}");
Console.WriteLine("container is null");
if (c.Containers == null) {
Console.WriteLine("containers is null");
foreach (var container in c.Containers) {
Console.WriteLine("container name: " + container.Name);
Console.WriteLine("items count: " + container.Items.Count.ToString());
foreach (var item in container.Items) {
Console.WriteLine("item is null");
Console.WriteLine("item C# type: " + item.GetType().Name);
Console.WriteLine("item type: " + item.Type);
Console.WriteLine("item base str: " + item.BasePropStr);
Console.WriteLine("item base int: " + item.BasePropInt.ToString());
if (item is ItemDerived1 derivA) {
Console.WriteLine("derived A prop: " + derivA.PropDerivA);
if (item is ItemDerived2 derivB) {
Console.WriteLine("derived B prop: " + derivB.PropDerivB);
if (item is SubItems subs) {
Console.WriteLine("subitem count: " + subs.Items.Count);
public abstract class ItemBase {
public string Type { get; set; }
public string BasePropStr { get; set; }
public int BasePropInt { get; set; }
public class ItemDerived1 : ItemBase {
public string PropDerivA { get; set; }
public class ItemDerived2 : ItemBase {
public int PropDerivB { get; set; }
public class SubItems : ItemBase {
public List<ItemBase> Items { get; set; }
public class SubContainer {
public string Name { get; set; }
public List<ItemBase> Items { get; set; }
public List<SubContainer> GetItems() {
public void AddSubContainer(SubContainer item) {
private List<SubContainer> _items = new List<SubContainer>();
public List<SubContainer> Containers {
return _context?.GetItems();
foreach (var item in value) {
_context.AddSubContainer(item);
private Context _context = new Context();