[Fork] [Fork] [Fork] [Fork] Deep Nested Object Properties Json Serialization

CSharp · Console

/Program.cs

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

public class Program
{
    public static void Main()
    {
		dynamic model = ChoExpandoObject.New("performanceLevels", 
											 new List<ChoExpandoObject>
											 {
												 ChoExpandoObject.New("performanceLevel_1",
																	  ChoExpandoObject.New(new string[] { "title", "version", "threelevels" },
																						   ChoExpandoObject.New(new string[] { "data-type", "source", "source-column", "default" }, 
																												"string", "column", "title-column", "N/A"),
																						   ChoExpandoObject.New(new string[] { "data-type", "source", "source-column", "default" },
																												"int", "column", "version-column", "1"),
																						   ChoExpandoObject.New("version",
																												ChoExpandoObject.New(new string[] { "data-type", "source", "source-column", "default" },
																																	 "int", "column", "version-column", "1")
																											   )
																						  )
																	 ),
												 ChoExpandoObject.New("performanceLevel_2",
																	  new List<ChoExpandoObject>
																	  {
																		  ChoExpandoObject.New("title", ChoExpandoObject.New(new string[] { "data-type", "source", "source-column", "default" },
																															 "string", "column", "title-column", "N/A")
																							  ),
																		  ChoExpandoObject.New("version", ChoExpandoObject.New(new string[] { "data-type", "source", "source-column", "default" },
																															   "int", "column", "version-column", "1")
																							  )
																	  }
																	 )
											 }
											);
		
		var settings = new JsonSerializerSettings()
        {
			Converters = new List<JsonConverter> { },
            Formatting = Formatting.Indented
        };

		var jsonMap = JsonConvert.SerializeObject(new List<ChoExpandoObject> { model }, settings);
        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 ChoExpandoObject : DynamicObject, IDictionary<string, object> //, IXmlSerializable
    {
        #region Instance Members

        private readonly object _padLock = new object();
        private IDictionary<string, object> _kvpDict = new Dictionary<string, object>();

        #endregion Instance Members

        #region Constructors

        public ChoExpandoObject()
        {

        }

        public ChoExpandoObject(IDictionary<string, object> kvpDict)
        {
            _kvpDict = kvpDict;
        }

        #endregion Constructors

        #region DynamicObject Overrides

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            return GetPropertyValue(binder.Name, out result);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            var key = binder.Name;
            return SetPropertyValue(key, value);
        }

        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        {
            result = null;

            if ((indexes.Length == 1) && indexes[0] != null)
            {
                if (indexes[0] is string)
                {
                    var key = indexes[0] as string;
                    return GetPropertyValue(key, out result);
                }
                else if (indexes[0] is int)
                {
                    var index = (int)indexes[0];

                    IDictionary<string, object> kvpDict = _kvpDict;
                    if (kvpDict != null)
                        result = kvpDict.ElementAt(index).Value;
                    return true;
                }
            }

            return false;
        }

        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
        {
            if ((indexes.Length == 1) && indexes[0] != null)
            {
                if (indexes[0] is string)
                {
                    var key = indexes[0] as string;
                    return SetPropertyValue(key, value);
                }
                else if (indexes[0] is int)
                {
                    var index = (int)indexes[0];

                    IDictionary<string, object> kvpDict = _kvpDict;
                    if (kvpDict != null)
                        kvpDict[kvpDict.ElementAt(index).Key] = value;
                    return true;
                }
            }
            return true;
        }

        #endregion DynamicObject Overrides

        #region Instance Members (Protected/Public)

        protected virtual bool GetPropertyValue(string name, out object result)
        {
            result = null;

            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                if (kvpDict.ContainsKey(name))
                    result = kvpDict[name];
                else
                {
                    return false;
                }
            }
            return true;
        }

        protected virtual bool SetPropertyValue(string name, object value)
        {
            if (IsReadOnly)
                return false;

            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                if (!kvpDict.ContainsKey(name))
                {
                    kvpDict.Add(name, value);
                }
                else
                    kvpDict[name] = value;
            }

            return true;
        }

        public static ChoExpandoObject New(Func<IEnumerable<KeyValuePair<string, object>>> func)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            if (func != null)
            {
                foreach (var kvp in func())
                    dict.Add(kvp.Key, kvp.Value);
            }
            return new ChoExpandoObject(dict);
        }

        public static ChoExpandoObject New(string key, object value)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add(key, value);
            return new ChoExpandoObject(dict);

        }

        public static ChoExpandoObject New(string[] keys, params object[] values)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            if (keys != null)
            {
                int counter = 0;
                foreach (var key in keys)
                {
                    if (counter < values.Length)
                        dict.Add(key, values[counter]);
                    else
                        dict.Add(key, null);
                    counter++;
                }
            }
            return new ChoExpandoObject(dict);
        }


        #endregion

        public ICollection<string> Keys
        {
            get
            {
                IDictionary<string, object> kvpDict = _kvpDict;
                return kvpDict != null ? kvpDict.Keys : null;
            }
        }

        public ICollection<object> Values
        {
            get
            {
                IDictionary<string, object> kvpDict = _kvpDict;
                return kvpDict != null ? kvpDict.Values : null;
            }
        }

        public int Count
        {
            get
            {
                IDictionary<string, object> kvpDict = _kvpDict;
                return kvpDict != null ? kvpDict.Count : 0;
            }
        }

        public bool IsReadOnly
		{
			get { return false; }
		}

        public object this[string key]
        {
            get
            {
                object result = null;
                GetPropertyValue(key, out result);
                return result;
            }

            set
            {
                SetPropertyValue(key, value);
            }
        }

        public bool ContainsKey(string key)
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            return kvpDict.ContainsKey(key);
        }

        public void Add(string key, object value)
        {
            SetPropertyValue(key, value);
        }

        public bool Remove(string key)
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null && kvpDict.ContainsKey(key))
            {
                kvpDict.Remove(key);
            }
            return false;
        }

        public bool TryGetValue(string key, out object value)
        {
            return GetPropertyValue(key, out value);
        }

        public void Add(KeyValuePair<string, object> item)
        {
            SetPropertyValue(item.Key, item.Value);
        }

        public void Clear()
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                kvpDict.Clear();
            }
        }

        public bool Contains(KeyValuePair<string, object> item)
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                return kvpDict.Contains(item);
            }
            return false;
        }

        public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                foreach (var kvp in kvpDict)
                {
                    array[arrayIndex++] = kvp;
                }
            }
        }

        public bool Remove(KeyValuePair<string, object> item)
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                return kvpDict.Contains(item);
            }
            return false;
        }

        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
        {
            IDictionary<string, object> kvpDict = _kvpDict;
            if (kvpDict != null)
            {
                foreach (var kvp in kvpDict)
                {
                    yield return kvp;
                }
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return Keys;
        }

    }
;