3

I'm receiving data in dictionary form and would like to deserialize it into a dynamic object. The twist is the dictionary keys express a hierarchical object. A second twist is some of the keys express an array and/or dictionary property.

For example:

===========Key================ ======Value========
Person.First                  | John
Person.Last                   | Doe
Person.Phone[Work]            | 999-555-1234
Person.Phone[Home]            | 999-555-1235
Person.Addresses[Home].Street | 101 My Street
Person.Addresses[Home].City   | AnyTown
Person.Spouse.First           | Jane
Person.Spouse.Last            | Doe
Person.Insurance[0].Name      | Medicare
Person.Insurance[0].GroupNum  | 1234567

Edit: Added array examples

I'm trying to find a simple method to create an object that can then be used in a runtime expressions evaluator.

Here's my first attempt that works for the simple properties, but doesn't attempt to handle the arrays

public static class DynamicBuilder
{
    public static object Build(IDictionary<string, object> dict)
    {

        ExpandoObject root = new ExpandoObject();

        foreach (var item in dict)
        {
            var objDict = (IDictionary<string, object>)root;

            var parts = item.Key.Split('.');

            for (int i = 0; i < parts.Length ; i++)
            {
                string propName = parts[i];

                if (i < parts.Length - 1)
                {
                    if (!objDict.ContainsKey(propName))
                    {
                        dynamic temp = new ExpandoObject();
                        objDict.Add(propName, temp);
                        objDict = (IDictionary<string, object>)temp;
                    }
                    else
                    {
                        objDict = (IDictionary<string, object>)objDict[propName];
                    }

                }
                else
                {
                    if (objDict.ContainsKey(propName))
                        objDict[propName] = item.Value;
                    else
                        objDict.Add(propName, item.Value);

                }

            }

        }

        return root;
    }

}

Any ideas on better way to approach this?

Thanks,

Rick
  • 5,029
  • 2
  • 33
  • 34
  • Are there actually array properties in the data? In your example you've only shown dictionary properties and I just want to make sure you're not confusing array definition with dictionary access. – alan Feb 08 '12 at 23:17
  • yes..I'll update the sample with the array example – Rick Feb 08 '12 at 23:57
  • Looks like a reasonable approach. Maybe one thing: you should split that method into smaller ones to improve readability. – svick Feb 09 '12 at 02:30

1 Answers1

0

A simple way would be just to make a custom object like

public class DictObject
{
   public String value;
   public Dictionary<string, DictObject> children;
}

Your main dictionary would just be a Dictionary<string, DictObject> object. For each property name you would add a dictionary entry and a value, or a child dictionary for the children.

So you would load up Person.First so that it would be accessed like

 MainDict("Person").children("First").Value 

And using that approach, you could simple represent your dictionary and array entries the same way as the . children as well, instead of treating them special. Visualize your data like this,

===========Key================ ======Value========
Person.First                  | John
Person.Last                   | Doe
Person.Phone.Work             | 999-555-1234
Person.Phone.Home             | 999-555-1235
Person.Addresses.Home.Street  | 101 My Street
Person.Addresses.Home.City    | AnyTown
Person.Spouse.First           | Jane
Person.Spouse.Last            | Doe
Person.Insurance.0.Name       | Medicare
Person.Insurance.0.GroupNum   | 1234567

So the values would be accessed like,

 MainDict("Person").children("Insurance").children("0").children("Name").Value 

And you could always add properties to the DictObject if you wanted to track dictionary/array if you wanted to output that same text file again.

Kratz
  • 4,280
  • 3
  • 32
  • 55