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;
public class PDItem : IDictionaryObject<List<IItem>>
public string Key { get; set; }
public List<IItem> Value { get; set; }
public interface IDictionaryObject<T>
public interface IItem: IElement
[JsonConverter(typeof(ElementConverter))]
public interface IElement
string elementType { get; }
public class ConcreteTypeA : IItem
public string elementType { get; set; }
public string inputType { get; set; }
public string name { get; set; }
public string label { get; set; }
public bool @checked { get; set; }
public class ElementConverter : JsonCreationConverter<IElement>
protected override IElement Create(Type objectType, JObject jObject)
return new ConcreteTypeA();
switch (jObject["elementType"].Value<string>())
case ElementTypeDescriptions.FirstType:
case ElementTypeDescriptions.SecondType:
case ElementTypeDescriptions.ThirdType:
case ElementTypeDescriptions.FourthType:
case ElementTypeDescriptions.FifthType:
throw new NotImplementedException("This object type is not yet implemented.");
public class PDItemConverter: JsonConverter<PDItem>
public override void WriteJson(JsonWriter writer, PDItem value, JsonSerializer serializer)
serializer.Serialize(writer, new Dictionary<string, List<IItem>> { { value.Key, value.Value } });
public override PDItem ReadJson(JsonReader reader, Type objectType, PDItem existingValue,
bool hasExistingValue, JsonSerializer serializer)
var dto = serializer.Deserialize<Dictionary<string, List<IItem>>>(reader);
throw new JsonSerializationException(string.Format("Incorrect number of dictionary keys: {0}", dto.Count));
existingValue = hasExistingValue ? existingValue : new PDItem();
existingValue.Key = pair.Key;
existingValue.Value = pair.Value;
public abstract class JsonCreationConverter<T> : JsonConverter
public override bool CanWrite { get { return false; } }
protected abstract T Create(Type objectType, JObject jObject);
public override bool CanConvert(Type objectType)
return typeof(T) == objectType;
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
var jObject = JObject.Load(reader);
var target = Create(objectType, jObject);
serializer.Populate(jObject.CreateReader(), target);
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
throw new NotImplementedException();
public static void Test()
static void TestRoundTrip()
var settings = new JsonSerializerSettings
Converters = { new PDItemConverter() },
var item = JsonConvert.DeserializeObject<PDItem>(json, settings);
var json2 = JsonConvert.SerializeObject(item, Formatting.Indented, settings);
Console.WriteLine("\nRound-tripped JSON: ");
Console.WriteLine(json2);
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2)));
static void TestSerialize()
PDItem item = new PDItem() {
Value = new List<IItem>() {
name = "another_checkbox",
label = "Another checkbox",
var settings = new JsonSerializerSettings
Converters = { new PDItemConverter() },
var json = JsonConvert.SerializeObject(item, Formatting.Indented, settings);
Console.WriteLine("\nSerialized {0}", item);
""elementType"": ""input"",
""inputType"": ""checkbox"",
""name"": ""another_checkbox"",
""label"": ""Another checkbox"",
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");