using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
public static void Main()
Console.WriteLine("----------------------\n First Call output\n----------------------");
"{\"ClosedParameters\":{\"4\":{\"key1\":1,\"key2\":\"value2\",\"key3\":[1,2,3]}}}";
var deserializeSettings = new JsonSerializerSettings
ContractResolver = new MyContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DateParseHandling = DateParseHandling.None
var t = JsonConvert.DeserializeObject<Ticket>(jsonString, deserializeSettings);
var ticket = new Ticket()
ClosedParameters = new Dictionary<byte, object>()
{"key3", new object[] { 1, 2, 3 } }
var json = JsonConvert.SerializeObject(ticket, new JsonSerializerSettings
NullValueHandling = NullValueHandling.Ignore,
DateParseHandling = DateParseHandling.None
Console.WriteLine("----------------------\n Serialization Result.\n----------------------");
Console.WriteLine("----------------------\n Second call output.\n----------------------");
var ticket2 = JsonConvert.DeserializeObject<Ticket>(jsonString, deserializeSettings);
public Dictionary<byte, object> ClosedParameters { get; set; } = new Dictionary<byte, object>();
public class MyContractResolver : DefaultContractResolver
protected override JsonDictionaryContract CreateDictionaryContract(Type objectType)
var contract = base.CreateDictionaryContract(objectType);
if (objectType == typeof(Dictionary<byte, object>))
contract.ItemConverter = new ClosedParametersConverter();
public class ClosedParametersConverter : JsonConverter
private int hashtableStarted;
private int recursionLevel = 0;
public override bool CanConvert(Type objectType)
throw new NotSupportedException();
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
Console.WriteLine($"ReadJson: {reader.TokenType} {reader.ValueType} {reader.Value} {reader.Depth} {reader.Path}");
if (++this.recursionLevel >= 50)
throw new InvalidOperationException("Recursion level exceeded");
if (reader.Path.Contains("ClosedParameters"))
switch (reader.TokenType)
case JsonToken.StartObject:
var r = serializer.Deserialize(reader, typeof(Hashtable));
if (this.hashtableStarted > 0)
return serializer.Deserialize(reader, typeof(int));
return serializer.Deserialize(reader, reader.ValueType);
case JsonToken.StartArray:
if (this.hashtableStarted > 0)
var o = serializer.Deserialize(reader, typeof(object[]));
return serializer.Deserialize(reader, reader.ValueType);
return serializer.Deserialize(reader, reader.ValueType);
return serializer.Deserialize(reader, objectType);
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
serializer.Serialize(writer, value);