Search code examples
c#.netjsonjson.netexpandoobject

Convert delimited string to Expando Object


I lave a dictionary like this -

Dictionary<string, Object> dict = new Dictionary<string, Object>();
dict.Add("event.data", "data");
dict.Add("event.Location", LocObj);
dict.Add("event.Details.Cost", CostObj);

I am trying to merge this with the existing json structure -

{
   "event" : {
       "name" : "Hello World",
       "tags" : [tags]
    }
    "sponsors" : {
       ...
    }
    "OtherObj" : {
       ...
    }
 }

I am trying to use ExpandoObject and then inject it into the original json, like this-

 foreach(KeyValuePair<string, Object> kvp in dict) {            

        var newObj= new ExpandoObject() as IDictionary<string, Object>;
        newObj.Add(kvp.Key, value);         

        existingObject.Merge(JObject.FromObject(newObj), new JsonMergeSettings
        {
            MergeArrayHandling = MergeArrayHandling.Union
        });
    }

   Console.WriteLine(JsonConvert.SerializeObject(existingObject));  

But when it gets serialized event.Location does not show up inside the existing event tag, instead it adds a new key called event.Location.

{
   "event" : {
       "name" : "Hello World",
       "tags" : [tags]
    },
    "event.Location" : { ... },   <---------------
    "event.data": { ... },        <---------------        
    "event.Details.Cost" : { ... }<---------------        
    "sponsors" : {
       ...
    },
    "OtherObj" : {
       ...
    }
 }

How do I fix the Expando obj creation to fix this?


Solution

  • See the below program. This will show an example of a working merge and breaking merge. The difference is how the object is structured. In one case, there is "Event.Location" which does not work. In the other case, the "Event" object contains a "Location" and it correctly nests in the JObject's merge operation.

    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.Dynamic;
    
    namespace DynamicSerial
    {
        class Program
        {
            static void Main(string[] args)
            {
                var myObject = new Dictionary<string, Object>();
                myObject.Add("Id", 1);
                myObject.Add("Event", new { Name = "SomeName", Id = 2 });
    
                var mergeObject = new Dictionary<string, Object>();
                mergeObject.Add("Event", new { Location = new { Name = "SomeLocation", Id = 3 } }); //WORKS
                //mergeObject.Add("Event.Location", new { Name = "SomeLocation", Id = 3 }); //DOES NOT WORK
    
                JObject myDynamicObject = JObject.FromObject(myObject);
    
                foreach (KeyValuePair<string, Object> kvp in mergeObject)
                {
    
                    var newObj = new ExpandoObject() as IDictionary<string, Object>;
                    newObj.Add(kvp.Key, kvp.Value);
    
                    myDynamicObject.Merge(JObject.FromObject(newObj), new JsonMergeSettings
                    {
                        MergeArrayHandling = MergeArrayHandling.Merge
                    });
                }
    
                Console.WriteLine(JsonConvert.SerializeObject(myDynamicObject));
    
            }
        }
    }
    

    The resulting JSON

    good:
    {"Id":1,"Event":{"Name":"SomeName","Id":2,"Location":{"Name":"SomeLocation","Id":3}}}
    bad:
    {"Id":1,"Event":{"Name":"SomeName","Id":2},"Event.Location":{"Name":"SomeLocation","Id":3}}
    

    In conclusion, you should change

    Dictionary<string, Object> dict = new Dictionary<string, Object>();
    dict.Add("event.data", "data");
    dict.Add("event.Location", LocObj);
    dict.Add("event.Details.Cost", CostObj);
    

    To

    Dictionary<string, Object> dict = new Dictionary<string, Object>();
    dict.Add("event", new { data="data", Location=LocObj, Details=new { Cost=CostObj } });