Kyle Kyle - 3 years ago 82
C# Question

How to deserialize string to object (string in format in similar to object notation)

I have a string that looks like this. It's not JSON and not XML.

{Foo={name=My Foo Value, active=true, some date=20170630}, Bar={name=My Bar Value}, Key With Space={name=Foo Bar, active=false}}


Here are the assumptions:


  1. Objects are enclosed by
    {}

  2. Keys can have a space in the name

  3. Keys are separated by a space and a comma (
    ,
    )

  4. Values are assigned to keys by an equal sign

  5. Keys can have multiple values and values are enclosed by
    {}
    , values inside the value are separated by a space and a comma (
    ,
    ). For example, this is a single key with three values:
    {My Foo Key={one=true, two=true, third value=false}}



My strategy is to deserialize to
Dictionary<string, object
at first, worry about recursion later. Any suggestions (existing library?) appreciated!

Here is what I have

var stringContentTrimmed = stringContent.Substring(1, stringContent.Length - 2);
var objects = stringContentTrimmed.Split(',')
.Select(x => x.Trim())
.Where(x => !String.IsNullOrWhiteSpace(x));


TLDR. The
Split
function is also splitting up my values, which isn't what I want.

enter image description here

Answer Source

I created a method GetObjects below which returns a Dictionary<string, string> of the top-level objects and the raw content inside. Another method, Merge returns a nested dictionary by calling GetValues to extract the key-value pairs from the object content.

Using your example string, the Merge method returns this: enter image description here

class Program
{
    static void Main(string[] args)
    {
        var str = "{Foo={name=Foo Value, active=true, some date=20170630}, Bar={name#=My Bar Value}, Key With Space={name=Foo Bar, active=false}}";

        var values = GetObjects(str);

        Dictionary<string, Dictionary<string, string>> objects = Merge(values);
    }

    public static Dictionary<string, Dictionary<string, string>> Merge(Dictionary<string, string> input)
    {
        var output = new Dictionary<string, Dictionary<string, string>>();

        foreach (var key in input.Keys)
        {
            var value = input[key];
            var subValues = GetValues(value);

            output.Add(key, subValues);
        }

        return output;
    }

    public static Dictionary<string, string> GetObjects(string input)
    {
        var objects = new Dictionary<string, string>();
        var objectNames = new Queue<string>();
        var objectBuffer = string.Empty;

        foreach (var c in input)
        {
            if (char.Equals('{', c))
            {
                if (!string.IsNullOrEmpty(objectBuffer))
                {
                    var b = objectBuffer.Trim('{', '}', ',', ' ', '=');
                    objectNames.Enqueue(b);
                }

                objectBuffer = string.Empty;
            }

            if (char.Equals('}', c))
            {
                if (objectNames.Count > 0)
                {
                    var b = objectBuffer.Trim('{');
                    var key = objectNames.Dequeue();

                    objects.Add(key, b);
                }

                objectBuffer = string.Empty;
            }

            objectBuffer += c;
        }

        return objects;
    }

    private static Dictionary<string, string> GetValues(string input)
    {
        var output = new Dictionary<string, string>();
        var values = input.Split(new string[] { ", " }, System.StringSplitOptions.None);

        foreach (var val in values)
        {
            var parts = val.Split('=');
            if (parts.Length == 2)
            {
                var key = parts[0].Trim(' ');
                var value = parts[1].Trim(' ');
                output.Add(key, value);
            }
        }

        return output;
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download