I want your help with a C# problem using Newtonsoft.Json, I want to serialize and deserialize a custom class that I've created,
which has a base and sub class and circular reference to it self,


here is my class structure, and wait for me to give you more info and what is the problem I am facing:

```
internal abstract class BlockBase
{
    public string Id { get; protected set; } = null!;
    public string BlockType { get; protected set; } = null!;
    public long UserId { get; set; }
    public BlockBase? PreviousBlock { get; set; }
    public BlockBase? NextBlock { get; set; }

    protected BlockBase() { }
    protected BlockBase(long userId) => UserId = userId;
}


internal class GatherBlock : BlockBase
{
    public int? DigitsLength { get; set; }
    public int? Timeout { get; set; }
    public SayBlock? SayBlock { get; set; }
    public Dictionary<string, BlockBase> RegexInputHandlers = new();

    public GatherBlock()
    {
        
    }
    public GatherBlock(long userId) : base(userId)
    {
        Id = Guid.NewGuid().ToString();
        BlockType = "Gather";
    }

    public GatherBlock(long userId, int? digitsLength = default, int? timeout = default, SayBlock? sayBlock = null, BlockBase? previousBlock = null, BlockBase? nextBlock = null)
    : this(userId, Guid.NewGuid().ToString(), digitsLength, timeout, sayBlock, previousBlock, nextBlock) { }

    public GatherBlock(long userId, string id, int? digitsLength = default, int? timeout = default,
        SayBlock? sayBlock = null, BlockBase? previousBlock = null, BlockBase? nextBlock = null) : base(userId)
    {
        Id = id;
        BlockType = "Gather";

        DigitsLength = digitsLength;
        Timeout = timeout;
        SayBlock = sayBlock;
        PreviousBlock = previousBlock;
        NextBlock = nextBlock;
    }
}


internal class SayBlock : BlockBase
{
    public string Message { get; set; } = string.Empty;
    public string Voice { get; set; } = "man";
    public string Language { get; set; } = "en-US";
    public int? Loop { get; set; }

    public SayBlock() { }
    public SayBlock(long userId) : base(userId)
    {
        Id = Guid.NewGuid().ToString();
        BlockType = "Say";
    }

    public SayBlock(long userId, string? message = null, string? voice = null, string? language = null, int? loop = default,
        BlockBase? previousBlock = null, BlockBase? nextBlock = null)
    : this(userId, Guid.NewGuid().ToString(), message, voice, language, loop, previousBlock, nextBlock) { }

    public SayBlock(long userId, string id, string? message = null, string? voice = null,
        string? language = null, int? loop = default, BlockBase? previousBlock = null, BlockBase? nextBlock = null) : base(userId)
    {
        Id = id;
        BlockType = "Say";

        Message = message ?? string.Empty;
        Voice = voice ?? "man";
        Language = language ?? "en-US";
        Loop = loop;
        PreviousBlock = previousBlock;
        NextBlock = nextBlock;
    }
}
```

And I have created some objects:

```
var rootBlock = new GatherBlock(userId)
{
        Timeout = 30,
        SayBlock = new SayBlock(userId)
        {
        Message = "Please enter your name and press # at the end."
        },
        RegexInputHandlers = { { "^[a-zA-Z0-9 .-#]{2,20}$", new SayBlock(userId, "Welcome {#input}", null, null, null, null, null) } }
};

rootBlock.NextBlock = new GatherBlock(userId)
{
        DigitsLength = 5,
        Timeout = 30,
        SayBlock = new SayBlock(userId)
        {
        Message = "Please enter your year of birth"
        },
        RegexInputHandlers = { { "^[0-9 #]{2,4}$", new SayBlock(userId, "Your year of birth is {#input}", null, null, null, null, null) } },
        PreviousBlock = rootBlock
};

var gatherBlock = new GatherBlock(userId)
{
        DigitsLength = 5,
        Timeout = 30,
        SayBlock = new SayBlock(userId)
        {
        Message = "Press 1 to continue, 2 to end the call, 3 to repeat."
        },
        RegexInputHandlers =
        {
        { "^1$", new SayBlock(userId, "Your choice is {#input}, which means to continue.", null, null, null, null, null) },
        { "^2$", new SayBlock(userId, "Your choice is {#input}, which means to repeat.", null, null, null, null, null) }
        },
        PreviousBlock = rootBlock.NextBlock
};
gatherBlock.RegexInputHandlers.Add("^3$", gatherBlock);
rootBlock.NextBlock.NextBlock = gatherBlock;
```

Here are the serialization settings and the converter I am using:

```
internal static class Helper
{
    public static JsonSerializerSettings BlockJsonSerializerSettings = new()
    {
        PreserveReferencesHandling = PreserveReferencesHandling.All,
        ReferenceLoopHandling = ReferenceLoopHandling.Serialize,

        Converters = { BlockBaseJsonConverter.Instance }
    };
}

internal class BlockBaseJsonConverter : JsonConverter<BlockBase>
{
    public static BlockBaseJsonConverter Instance { get; } = new();

    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, BlockBase? value, JsonSerializer serializer) => throw new NotImplementedException();

    public override BlockBase? ReadJson(JsonReader reader, Type objectType, BlockBase? existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var blockType = jsonObject.GetValue("BlockType", StringComparison.OrdinalIgnoreCase)?.Value<string>();

        return blockType switch
        {
            "Say" => jsonObject.ToObject<SayBlock>(),
            "Gather" => jsonObject.ToObject<GatherBlock>(),
            _ => null
        };
    }
}
```

I serialize the 'rootBlock' which I created in the above code.

```
var serializeObject = JsonConvert.SerializeObject(rootBlock, Helper.BlockJsonSerializerSettings);
```

which gives me the following serialized string:

{"$id":"1","RegexInputHandlers":{"$id":"2","^[a-zA-Z0-9 .-#]{2,20}$":{"$id":"3","Message":"Welcome {#input}","Voice":"man","Language":"en-US","Loop":null,"Id":"cfac8bec-5714-4832-8415-629e9e324728","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null}},"DigitsLength":null,"Timeout":30,"SayBlock":{"$id":"4","Message":"Please enter your name and press # at the end.","Voice":"man","Language":"en-US","Loop":null,"Id":"2669517e-006e-4bdd-a45d-b653187b6f6a","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null},"Id":"c5cbce64-8a97-403d-b95f-82685515c938","BlockType":"Gather","UserId":2016867034,"PreviousBlock":null,"NextBlock":{"$id":"5","RegexInputHandlers":{"$id":"6","^[0-9 #]{2,4}$":{"$id":"7","Message":"Your year of birth is {#input}","Voice":"man","Language":"en-US","Loop":null,"Id":"dd5aea60-6ce4-46e2-a960-93be3df88ee0","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null}},"DigitsLength":5,"Timeout":30,"SayBlock":{"$id":"8","Message":"Please enter your year of birth","Voice":"man","Language":"en-US","Loop":null,"Id":"e50fd488-848d-496d-bcf3-7768f0f0d323","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null},"Id":"97b8fd48-b1fe-4ba4-9ac9-5fe16394ddb6","BlockType":"Gather","UserId":2016867034,"PreviousBlock":{"$ref":"1"},"NextBlock":{"$id":"9","RegexInputHandlers":{"$id":"10","^1$":{"$id":"11","Message":"Your choice is {#input}, which means to continue.","Voice":"man","Language":"en-US","Loop":null,"Id":"ae677014-912b-4ec5-b6cf-913be20be8ac","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null},"^2$":{"$id":"12","Message":"Your choice is {#input}, which means to repeat.","Voice":"man","Language":"en-US","Loop":null,"Id":"1c996652-90d8-41b3-ab8a-dfa3658a347a","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null},"^3$":{"$ref":"9"}},"DigitsLength":5,"Timeout":30,"SayBlock":{"$id":"13","Message":"Press 1 to continue, 2 to end the call, 3 to repeat.","Voice":"man","Language":"en-US","Loop":null,"Id":"f9f03d89-7d16-4257-8c21-19b768726bd5","BlockType":"Say","UserId":2016867034,"PreviousBlock":null,"NextBlock":null},"Id":"d7386caf-e467-4f9e-88f1-761cb7b44ead","BlockType":"Gather","UserId":2016867034,"PreviousBlock":{"$ref":"5"},"NextBlock":null}}}

Now for the problem, when I try to deserialize the serialized string with:

```
var objectAgain = JsonConvert.DeserializeObject<BlockBase>(serializeObject, Helper.BlockJsonSerializerSettings);
```

I got the following error:

Newtonsoft.Json.JsonSerializationException: Could not create an instance of type OtpTwilioBot.Models.BlockBase. Type is an interface or abstract class and cannot be instantiated. Path 'RegexInputHandlers['^[a-zA-Z0-9 .-#]{2,20}$'].Message', line 1, position 90.