Deep Nested Object Properties Json Serialization

CSharp · Console

/Program.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class Program
{
    public static void Main()
    {
        var dataMapperModels = new List<DataMapper>();

        var model = new DataMapper
        {
            Name = "performanceLevels",
            SubDataMappers = new List<DataMapper>()
            {
                new DataMapper()
                {
                    Name = "performanceLevel_1",
                    SubDataMappers = new List<DataMapper>()
                    {
                        new DataMapper()
                        {
                            Name = "title",
                            DataMapperProperty = new DataMapperProperty()
                                    {
                                        Source = "column",
                                        SourceColumn = "title-column",
                                        DataType = "string",
                                        Default = "N/A",
                                        SourceTable = null,
                                        Value = null
                                    }
                        },
                        new DataMapper()
                        {
                            Name = "version",
                            DataMapperProperty = new DataMapperProperty()
                                    {
                                        Source = "column",
                                        SourceColumn = "version-column",
                                        DataType = "int",
                                        Default = "1",
                                        SourceTable = null,
                                        Value = null
                                    }
                        }
                    }
                },
                new DataMapper()
                {
                    Name = "performanceLevel_2",
                    SubDataMappers = new List<DataMapper>()
                    {
                        new DataMapper()
                        {
                            Name = "title",
                            DataMapperProperty = new DataMapperProperty()
                                    {
                                        Source = "column",
                                        SourceColumn = "title-column",
                                        DataType = "string",
                                        Default = "N/A",
                                        SourceTable = null,
                                        Value = null
                                    }
                        },
                        new DataMapper()
                        {
                            Name = "version",
                            DataMapperProperty = new DataMapperProperty()
                                    {
                                        Source = "column",
                                        SourceColumn = "version-column",
                                        DataType = "int",
                                        Default = "1",
                                        SourceTable = null,
                                        Value = null
                                    }
                        }
                    }
                }
            }
        };


        dataMapperModels.Add(model);

        var jsonMap = JsonConvert.SerializeObject(dataMapperModels, new JsonSerializerSettings()
        {
            Formatting = Formatting.Indented
        });

        Console.WriteLine(jsonMap);
    }

    /* GOAL:
    [
       {
          "performanceLevels":[
             {
                "performanceLevel_1":{
                   "title":{
                      "data-type":"string",
                      "source":"column",
                      "source-column":"title-column",
                      "default":"N/A"
                   },
                   "version":{
                      "data-type":"int",
                      "source":"column",
                      "source-column":"version-column",
                      "default":"1"
                   }
                }
             },
             {
                "performanceLevel_2":{
                   "title":{
                      "data-type":"string",
                      "source":"column",
                      "source-column":"title-column",
                      "default":"N/A"
                   },
                   "version":{
                      "data-type":"int",
                      "source":"column",
                      "source-column":"version-column",
                      "default":"1"
                   }
                }
             }
          ]
       }
    ]
    */
}

public class DataMapperJsonSerializer : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value is DataMapper)
        {
            var dataMapper = (DataMapper)value;
            if (dataMapper.SubDataMappers.Any())
            {
                writer.WriteStartObject();
                writer.WritePropertyName(dataMapper.Name);
                writer.WriteStartArray();
                //
                dataMapper.SubDataMappers.ForEach(sub =>
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName(sub.Name);
                    serializer.Serialize(writer, sub.SubDataMappers);
                    //if (sub.SubDataMappers.Any())
                    //{
                    //    sub.SubDataMappers.ForEach(tri =>
                    //    {
                    //        writer.WriteStartObject();
                    //        writer.WritePropertyName(tri.Name);
                    //        serializer.Serialize(writer, tri.DataMapperProperty);
                    //        writer.WriteEndObject();
                    //    });
                    //}
                    writer.WriteEndObject();
                });
                //
                writer.WriteEndArray();
                writer.WriteEndObject();
            }
            else
            {
                writer.WriteStartObject();
                writer.WritePropertyName(dataMapper.Name);
                serializer.Serialize(writer, dataMapper.DataMapperProperty);
                writer.WriteEndObject();
            }
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jsonObject = JObject.Load(reader);
        var properties = jsonObject.Properties().ToList();
        return new DataMapper()
        {
            Name = properties[0].Name,
            DataMapperProperty = (DataMapperProperty)properties[0].Value
        };
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(DataMapper).IsAssignableFrom(objectType);
    }
}


[JsonConverter(typeof(DataMapperJsonSerializer))]
public class DataMapper
{
    public DataMapper()
    {
        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")
        };
    }
}
;