using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public MyData(string value, string startDate, string endDate)
this.StartDate = startDate;
public string Value { get; }
public string StartDate { get; }
public string EndDate { get; }
public class MyOuterClassBase
public MyData Data { get; set; }
public class MyOuterClass : MyOuterClassBase
public MyOuterClass(MyData data)
public sealed class MyCustomConverter : JsonConverter
public override bool CanWrite => false;
public override bool CanConvert(Type objectType)
return objectType == typeof(MyOuterClassBase);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
JObject jObject = (JObject)JToken.ReadFrom(reader);
using (JsonReader jsonReader = jObject.CreateReader())
return serializer.Deserialize(jsonReader, typeof(MyOuterClass));
public static void Test()
var jsonFilePath = @"Question71709697.json";
File.WriteAllText(jsonFilePath, json);
var jsonSettings = new JsonSerializerSettings();
jsonSettings.ContractResolver = new DefaultContractResolver()
NamingStrategy = new CamelCaseNamingStrategy()
jsonSettings.Converters.Add(new StringEnumConverter());
jsonSettings.Formatting = Formatting.Indented;
jsonSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
jsonSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffffffZ";
jsonSettings.DateParseHandling = DateParseHandling.DateTimeOffset;
jsonSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
jsonSettings.NullValueHandling = NullValueHandling.Ignore;
jsonSettings.FloatParseHandling = FloatParseHandling.Double;
jsonSettings.TypeNameHandling = TypeNameHandling.None;
jsonSettings.Converters.Add(new MyCustomConverter());
MyOuterClassBase myOuterClass;
using (FileStream fileStream = File.OpenRead(jsonFilePath))
using (StreamReader streamReader = new StreamReader(fileStream))
using (JsonTextReader jsonReader = new JsonTextReader(streamReader))
myOuterClass = (MyOuterClassBase)JsonSerializer.CreateDefault(jsonSettings).Deserialize(jsonReader, typeof(MyOuterClassBase));
Console.WriteLine($"myData.StartDate={myOuterClass.Data.StartDate}, myData.EndDate={myOuterClass.Data.EndDate}");
jsonSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
var json2 = JsonConvert.SerializeObject(myOuterClass, Formatting.Indented, jsonSettings);
Console.WriteLine("Re-serialized {0}:", myOuterClass);
Console.WriteLine(json2);
Assert.AreEqual(json, json2);
static string GetJson() => @"{
""startDate"": ""2021-01-16T00:00:00.000Z"",
""endDate"": ""2021-01-18T00:00:00.000Z""
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , Environment.Version);
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
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)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None)
while (reader.TokenType == JsonToken.Comment)
public static JsonReader ReadAndAssert(this JsonReader reader)
throw new ArgumentNullException();
throw new JsonReaderException("Unexpected end of JSON stream.");