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 interface IMachineInfo
public class Machine1 : IMachineInfo
public double powerWatts { get; set; }
public double radiation { get; set; }
public double current { get; set; }
public class Machine2 : IMachineInfo
public double dbm { get; set; }
public double magneticField { get; set; }
public double frequency { get; set; }
public abstract class JsonListItemTypeInferringConverterBase<TItem> : JsonConverter
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
protected abstract bool TryInferItemType(Type objectType, JToken json, out Type type);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonArrayContract;
if (contract == null || contract.IsMultidimensionalArray || objectType.IsArray)
throw new JsonSerializationException(string.Format("Invalid array contract for {0}", objectType));
if (reader.MoveToContent().TokenType == JsonToken.Null)
if (reader.TokenType != JsonToken.StartArray)
throw new JsonSerializationException(string.Format("Expected {0}, encountered {1} at path {2}", JsonToken.StartArray, reader.TokenType, reader.Path));
var collection = existingValue as IList<TItem> ?? (IList<TItem>)contract.DefaultCreator();
switch (reader.TokenType)
var token = JToken.Load(reader);
if (!TryInferItemType(typeof(TItem), token, out itemType))
collection.Add((TItem)serializer.Deserialize(token.CreateReader(), itemType));
throw new JsonSerializationException("Unclosed array at path: " + reader.Path);
public override bool CanConvert(Type objectType)
return objectType.IsAssignableFrom(typeof(List<TItem>));
public static partial class JsonExtensions
public static JsonReader MoveToContent(this JsonReader reader)
while ((reader.TokenType == JsonToken.Comment || reader.TokenType == JsonToken.None) && reader.Read())
public class Machine1ListConverter<TMachineInfo> : JsonListItemTypeInferringConverterBase<TMachineInfo> where TMachineInfo : IMachineInfo
protected override bool TryInferItemType(Type objectType, JToken json, out Type type)
var obj = json as JObject;
if (obj != null && obj.GetValue("powerWatts", StringComparison.OrdinalIgnoreCase) != null)
public static void Test()
static void TestInterface()
var jsonString = GetJson();
var settings = new JsonSerializerSettings
Converters = { new Machine1ListConverter<IMachineInfo>() },
var list = JsonConvert.DeserializeObject<List<IMachineInfo>>(jsonString, settings);
Console.WriteLine("De-serialized and reserialized {0}: ", list.GetType().FullName);
Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
Assert.IsTrue(list.Count == JArray.Parse(jsonString).SelectTokens("[*].powerWatts").Count());
static void TestConcrete()
var jsonString = GetJson();
var settings = new JsonSerializerSettings
Converters = { new Machine1ListConverter<Machine1>() },
var list = JsonConvert.DeserializeObject<List<Machine1>>(jsonString, settings);
Console.WriteLine("De-serialized and reserialized {0}: ", list.GetType().FullName);
Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
Assert.IsTrue(list.Count == JArray.Parse(jsonString).SelectTokens("[*].powerWatts").Count());
""windowsTime"": ""2019-01-14T18:47:55.8390256-06:00"",
""irigTime"": ""0001-01-01T00:00:00"",
""messageTypeFlag"": ""Q"",
""magneticField "": ""8967"",
""frequency"": ""34500"",
""windowsTime"": ""2019-01-14T18:47:55.8390256-06:00"",
""irigTime"": ""0001-01-01T00:00:00"",
""messageTypeFlag"": ""Q"",
""powerWatts"": ""4000"",
""windowsTime"": ""2019-01-14T18:47:55.8390256-06:00"",
""irigTime"": ""0001-01-01T00:00:00"",
""messageTypeFlag"": ""Q"",
""powerWatts"": ""4000"",
""windowsTime"": ""2019-01-14T18:47:55.8390258-06:00"",
""irigTime"": ""0001-01-01T00:00:00"",
""messageTypeFlag"": ""Q"",
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: ");