using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class JsonPathConverter : JsonConverter
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonObjectContract ?? throw new JsonException(string.Format("{0} is not a JSON object", objectType));
var jo = JToken.Load(reader);
if (jo.Type == JTokenType.Null)
else if (jo.Type != JTokenType.Object)
throw new JsonSerializationException(string.Format("Unexpected token {0}", jo.Type));
var targetObj = contract.DefaultCreator();
foreach (var callback in contract.OnDeserializingCallbacks)
callback(targetObj, serializer.Context);
foreach (var property in contract.Properties)
if (property.Ignored || !property.Writable)
if (property.ShouldDeserialize != null && !property.ShouldDeserialize(targetObj))
var jsonPath = property.PropertyName;
var token = jo.SelectToken(jsonPath);
if (token != null && token.Type != JTokenType.Null)
if (property.Converter != null && property.Converter.CanRead)
using (var subReader = token.CreateReader())
if (subReader.TokenType == JsonToken.None)
value = property.Converter.ReadJson(subReader, property.PropertyType, property.ValueProvider.GetValue(targetObj), serializer);
value = token.ToObject(property.PropertyType, serializer);
property.ValueProvider.SetValue(targetObj, value);
foreach (var callback in contract.OnDeserializedCallbacks)
callback(targetObj, serializer.Context);
public override bool CanConvert(Type objectType) => false;
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer) => throw new NotImplementedException();
public class PrefixingStringConverter : JsonConverter<string>
public const string prefix = "prefix: ";
public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
writer.WriteValue(prefix + value);
public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.Null)
else if (reader.TokenType == JsonToken.String)
return prefix + (string)reader.Value;
return (string)JToken.Load(reader);
[JsonConverter(typeof(JsonPathConverter))]
public class EmployeeStackoverflow
[JsonProperty("response.code")]
[JsonConverter(typeof(PrefixingStringConverter))]
public string CodeResponse { get; set; }
[JsonProperty("employee.name")]
public string Name { get; set; }
[JsonProperty("employee.surname")]
public string Surname { get; set; }
[JsonProperty("employee.work")]
public string Workplace { get; set; }
public string IgnoreMe { get { return "Ignore Me"; } set { throw new NotImplementedException(); } }
internal void OnDeserializedMethod(StreamingContext context)
bool onDeserializingCalled = false;
void OnDeserializing(StreamingContext context)
onDeserializingCalled = true;
public bool OnDeserializingCalled => onDeserializingCalled;
public static void Test()
'description': 'Response success',
var employee = JsonConvert.DeserializeObject<EmployeeStackoverflow>(json);
Assert.IsTrue(employee.CodeResponse.StartsWith(PrefixingStringConverter.prefix));
Assert.IsTrue(employee.Workplace == "At Home!!");
Assert.IsTrue(employee.OnDeserializingCalled);
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];