Reputation: 4453
In C# I have a flat Dictionary<string, string>
where keys are in form of obj1/obj2/obj3
and values are direct string. Now I want to serialize that into subobjects, so example values:
var dict = new Dictionary<string, string> { {"foo/bar/baz1", "123" }, {"foo/baz", "456" }, { "foo/abc", "def" } };
should result with:
{
"foo": {
"bar": {
"baz1": "123"
},
"baz": "456",
"abc": "def"
}
}
Optionally I want to remove quotes around "123" and "456" in output if they can be interpreted as numbers or booleans.
I am using Newtonsoft.JSON
Upvotes: 4
Views: 241
Reputation: 23238
You can parse a source dictionary into JObject
using JObject.FromObject
method. Then go through all of properties, split them using string.Split
and parse recursively to a new JObject
, representing a properties tree. Finally add this object to the destination one using JObject.Add
, or update it if the given key is already exist
var dict = new Dictionary<string, string> { { "foo/bar/baz1", "123" }, { "foo/baz", "456" }, { "foo/abc", "def" } };
var source = JObject.FromObject(dict);
var dest = new JObject();
foreach (var property in source.Properties())
{
//split the name into parts
var items = property.Name.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
var item = items.FirstOrDefault();
if (string.IsNullOrEmpty(item))
continue;
//get JObject representing a properties tree
var result = WriteItems(items.Skip(1).ToList(), property.Value);
//check that destination already contains top property name (e.g. 'foo')
if (dest.ContainsKey(item))
{
(dest[item] as JObject)?.Add(result.First);
}
else
{
dest.Add(item, result);
}
}
Console.WriteLine(dest.ToString());
//local function to recursively go through all properties and create a result JObject
JObject WriteItems(IList<string> items, JToken value)
{
var item = items.FirstOrDefault();
items.RemoveAt(0);
if (!items.Any()) //no more items in keys, add the value
return new JObject(new JProperty(item, value));
return new JObject(new JProperty(item, WriteItems(items, value)));
}
It produces the following output
{
"foo": {
"bar": {
"baz1": "123"
},
"baz": "456",
"abc": "def"
}
}
Also, the code above allows you to handle a properties tree with any depth. I don't think that there is a built-in way to serialize the structure like foo/bar/baz1
into sub-objects in Json.NET
Upvotes: 4