using System.Collections.Generic;
using Newtonsoft.Json.Linq;
public static void Main()
var dataMapperModels = new List<DataMapper>();
var model = new DataMapper
Name = "performanceLevels",
SubDataMappers = new List<DataMapper>()
Name = "performanceLevel_1",
SubDataMappers = new List<DataMapper>()
DataMapperProperty = new DataMapperProperty()
SourceColumn = "title-column",
DataMapperProperty = new DataMapperProperty()
SourceColumn = "version-column",
SubDataMappers = new List<DataMapper>()
DataMapperProperty = new DataMapperProperty()
SourceColumn = "version-column",
Name = "performanceLevel_2",
SubDataMappers = new List<DataMapper>()
DataMapperProperty = new DataMapperProperty()
SourceColumn = "title-column",
DataMapperProperty = new DataMapperProperty()
SourceColumn = "version-column",
dataMapperModels.Add(model);
var settings = new JsonSerializerSettings()
Converters = new List<JsonConverter> { new DataMapperListConverter() },
Formatting = Formatting.Indented
var jsonMap = JsonConvert.SerializeObject(dataMapperModels, settings);
Console.WriteLine(jsonMap);
Console.WriteLine("\n------------------------------");
var list = JsonConvert.DeserializeObject<List<DataMapper>>(jsonMap, settings);
private static void Dump(List<DataMapper> list, string indent = "")
foreach (DataMapper mapper in list)
Console.WriteLine(indent + "Name: " + mapper.Name);
if (mapper.DataMapperProperty != null)
Console.WriteLine(indent + "DataType: " + mapper.DataMapperProperty.DataType);
Console.WriteLine(indent + "Source: " + mapper.DataMapperProperty.Source);
Console.WriteLine(indent + "SourceColumn: " + mapper.DataMapperProperty.SourceColumn);
Console.WriteLine(indent + "Default: " + mapper.DataMapperProperty.Default);
if (mapper.SubDataMappers != null && mapper.SubDataMappers.Count > 0)
Console.WriteLine(indent + "SubMappers:");
Dump(mapper.SubDataMappers, indent + " ");
public class DataMapperListConverter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(List<DataMapper>);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
List<DataMapper> list = (List<DataMapper>)value;
if (list.Any(dm => dm.DataMapperProperty != null))
JObject obj = new JObject(list.Select(dm =>
if (dm.DataMapperProperty != null)
val = JToken.FromObject(dm.DataMapperProperty, serializer);
val = JToken.FromObject(dm.SubDataMappers, serializer);
return new JProperty(dm.Name, val);
serializer.Serialize(writer,
list.Select(dm => new Dictionary<string, List<DataMapper>>
{ dm.Name, dm.SubDataMappers }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
return token.Children<JProperty>()
DataMapper mapper = new DataMapper { Name = jp.Name };
if (val["data-type"] != null)
mapper.DataMapperProperty = jp.Value.ToObject<DataMapperProperty>(serializer);
mapper.SubDataMappers = jp.Value.ToObject<List<DataMapper>>(serializer);
else if (token.Type == JTokenType.Array)
return token.Children<JObject>()
.SelectMany(jo => jo.Properties())
.Select(jp => new DataMapper
SubDataMappers = jp.Value.ToObject<List<DataMapper>>(serializer)
throw new JsonException("Unexpected token type: " + token.Type.ToString());
SubDataMappers = new List<DataMapper>();
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public DataMapperProperty DataMapperProperty { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<DataMapper> SubDataMappers { get; set; }
public class DataMapperProperty
[JsonProperty(PropertyName = "data-type", NullValueHandling = NullValueHandling.Ignore)]
public string DataType { get; set; }
[JsonProperty(PropertyName = "source", NullValueHandling = NullValueHandling.Ignore)]
public string Source { get; set; }
[JsonProperty(PropertyName = "source-column", NullValueHandling = NullValueHandling.Ignore)]
public string SourceColumn { get; set; }
[JsonProperty(PropertyName = "source-table", NullValueHandling = NullValueHandling.Ignore)]
public string SourceTable { get; set; }
[JsonProperty(PropertyName = "default", NullValueHandling = NullValueHandling.Ignore)]
public string Default { get; set; }
[JsonProperty(PropertyName = "value", NullValueHandling = NullValueHandling.Ignore)]
public string Value { get; set; }
public static explicit operator DataMapperProperty(JToken v)
return new DataMapperProperty()
DataType = v.Value<string>("data-type"),
Source = v.Value<string>("source"),
SourceColumn = v.Value<string>("source-column"),
SourceTable = v.Value<string>("source-table"),
Default = v.Value<string>("default"),
Value = v.Value<string>("value")