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 IElementWriter
string Name { get; set; }
public interface IElementUpdateWriter : IElementWriter
string FirstName { get; set; }
public interface IElementInsertWriter : IElementWriter
DateTime? CreationDate { get; set; }
public class Element:IElementWriter, IElementInsertWriter, IElementUpdateWriter {
public int ID { get; set; }
public string Name { get; set; }
public DateTime? CreationDate { get; set; }
public string FirstName { get; set; }
public class UpcastingContractResolver<TDerived, TBase> : DefaultContractResolver where TDerived: TBase
readonly HashSet<string> baseProperties = ((JsonObjectContract)JsonSerializer.Create().ContractResolver.ResolveContract(typeof(TBase)))
.Properties.Select(p => p.UnderlyingName)
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
var properties = base.CreateProperties(type, memberSerialization);
if (type == typeof(TDerived) || type.IsSubclassOf(typeof(TDerived)))
foreach (var property in properties)
if (!baseProperties.Contains(property.UnderlyingName))
static IContractResolver elementAsElementWriterResolver = new UpcastingContractResolver<Element, IElementWriter>();
public static void Test()
var dateTime = DateTime.Parse("2019-06-05T00:00:00+02:00", CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
IElementWriter element = new Element() { ID = 1, Name = "SourceName", CreationDate=dateTime, FirstName="SourceFirstName" };
var oldJson = JToken.FromObject(element);
string json = "{ id:'8', Name:'newName', FirstName:'newFirstName' }";
Console.WriteLine(oldJson.ToString(Formatting.None));
Console.WriteLine(JToken.Parse(json).ToString(Formatting.None));
JsonConvert.PopulateObject(json, element, new JsonSerializerSettings
ContractResolver = elementAsElementWriterResolver
var newJson = JToken.FromObject(element);
Console.WriteLine(newJson.ToString(Formatting.None));
var requiredJson = @"{""ID"":1,""Name"":""newName"",""CreationDate"":""2019-06-04T22:00:00Z"",""FirstName"":""SourceFirstName""}";
Assert.IsTrue(JToken.DeepEquals(newJson, JToken.Parse(requiredJson)));
Assert.IsTrue(JToken.DeepEquals(oldJson["ID"], newJson["ID"]));
Assert.IsTrue(JToken.DeepEquals(oldJson["CreationDate"], newJson["CreationDate"]));
Assert.IsTrue(JToken.DeepEquals(oldJson["FirstName"], newJson["FirstName"]));
Assert.IsTrue(JToken.DeepEquals(JToken.Parse(json)["Name"], newJson["Name"]));
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: ");