using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using System.Runtime.Serialization;
[JsonConverter(typeof(CustomElementJsonConverter))]
[JsonProperty("data", Required = Required.Always)]
public Sequence Sequence { get; set; }
public List<ElementData> Elements { get; set; }
public List<Step> Steps { get; set; }
public class CustomElementJsonConverter : JsonConverter<Step>
private static readonly Dictionary<string, JsonConverter> _converters;
static CustomElementJsonConverter()
foreach (var elementType in Enum.GetValues(typeof(ElementType)).Cast<ElementType>())
var elemTypeJsonName = elementType.GetEnumMemberValue().ToLower();
_converters[elemTypeJsonName] = ElementJsonConverterFactory.Create(elementType);
public override Step ReadJson(JsonReader reader, Type objectType, Step existingValue, bool hasExistingValue, JsonSerializer serializer)
var jElements = JArray.Load(reader);
var elements = new List<ElementData>();
foreach (var jElement in jElements)
var elementType = jElement["type"].Value<string>().ToLower();
var convertor = _converters[elementType];
return new Step { Elements = elements };
public static class ElementJsonConverterFactory
public static JsonConverter Create(ElementType elementType) => elementType switch
ElementType.Type1 => new ElementType1JsonConverter(),
ElementType.Type2 => new ElementType2JsonConverter()
public class ElementType1JsonConverter : JsonConverter<ElementData>
public override ElementData ReadJson(JsonReader reader, Type objectType, ElementData existingValue, bool hasExistingValue, JsonSerializer serializer)
public override void WriteJson(JsonWriter writer, ElementData value, JsonSerializer serializer)
throw new NotImplementedException();
public class ElementType2JsonConverter : JsonConverter<ElementData>
public override ElementData ReadJson(JsonReader reader, Type objectType, ElementData existingValue, bool hasExistingValue, JsonSerializer serializer)
public override void WriteJson(JsonWriter writer, ElementData value, JsonSerializer serializer)
throw new NotImplementedException();
[EnumMember(Value = "type1")] Type1,
[EnumMember(Value = "type2")] Type2,
[JsonProperty("type", Required = Required.Always)]
public ElementType ElementType { get; set; }
public class CommandElementData1 : ElementData
[EnumMember] Command1_Type1,
[EnumMember] Command2_Type1,
[JsonProperty(Required = Required.Always)]
public CommandType Command { get; set; }
public class ElementData_For_Command1Type1 : CommandElementData1
[JsonProperty(Required = Required.Always)]
public string Prop1 { get; set; }
[JsonProperty(Required = Required.Always)]
public string Prop2 { get; set; }
public class ElementData_For_Command2Type1 : CommandElementData1
[JsonProperty(Required = Required.Always)]
public string Prop1 { get; set; }
[JsonProperty(Required = Required.Always)]
public string Prop2 { get; set; }
public class CommandElementData2 : ElementData
[EnumMember] Command1_Type2,
[JsonProperty(Required = Required.Always)]
public CommandType Command { get; set; }
public class ElementData_For_Command1Type2 : CommandElementData2
[JsonProperty(Required = Required.Always)]
public int Prop3 { get; set; }
public static void Test()
static string GetJson() =>@"
public static partial class JsonExtensions
public static JsonReader AssertTokenType(this JsonReader reader, JsonToken tokenType) =>
reader.TokenType == tokenType ? reader : throw new JsonSerializationException(string.Format("Unexpected token {0}, expected {1}", reader.TokenType, tokenType));
public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
reader.ReadAndAssert().MoveToContentAndAssert();
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
ArgumentNullException.ThrowIfNull(reader);
if (reader.TokenType == JsonToken.None)
while (reader.TokenType == JsonToken.Comment)
public static JsonReader ReadAndAssert(this JsonReader reader)
ArgumentNullException.ThrowIfNull(reader);
throw new JsonReaderException("Unexpected end of JSON stream.");
public static void Main()
Console.WriteLine("Environment version: {0} ({1}), {2}", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version, Environment.OSVersion);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Namespace, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");