using System.Collections.Generic;
using Newtonsoft.Json.Linq;
public static void Main()
""records"": [""some value 1"", ""some value 2""],
var settings = new JsonSerializerSettings();
settings.Converters.Add(new NestedJsonConverter<SomeModel>());
var result = JsonConvert.DeserializeObject<SomeModel>(json , settings);
Console.WriteLine($"Nested value: {result.SomeValue}");
Console.WriteLine($"Array item #1: {result.Records[0]}");
Console.WriteLine($"Array item #2: {result.Records[1]}");
Console.WriteLine($"Class: {result.Data.Value}");
public class NestedJsonConverter<T> : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(T);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var data = JObject.Load(reader);
.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
foreach (var propertyInfo in properties)
var jsonPropertyAttribute = propertyInfo
.GetCustomAttributes(false)
.FirstOrDefault(attribute => attribute is JsonPropertyAttribute);
var propertyName = jsonPropertyAttribute != null
? ((JsonPropertyAttribute)jsonPropertyAttribute).PropertyName
if (string.IsNullOrEmpty(propertyName))
var names = propertyName.Split('/');
object propertyValue = null;
for (int i = 0; i < names.Length; i++)
var isLast = i == names.Length - 1;
? data.GetValue(name, StringComparison.OrdinalIgnoreCase)
: ((JObject)token).GetValue(name, StringComparison.OrdinalIgnoreCase);
if (token is JValue || token is JArray || (token is JObject && isLast))
propertyValue = token.ToObject(propertyInfo.PropertyType, serializer);
if (propertyValue == null)
propertyInfo.SetValue(result, propertyValue);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
public List<string> Records { get; set; }
public AnotherClass Data { get; set; }
[JsonProperty("level1/level2/level3")]
public string SomeValue{ get; set; }
public class AnotherClass
public string Value { get; set; }