Сериализация плоского словаря в мульти-субобъект JSON - PullRequest
4 голосов
/ 15 марта 2020

В C# У меня есть квартира Dictionary<string, string>, где ключи имеют форму obj1/obj2/obj3, а значения - прямые строки. Теперь я хочу сериализовать это в подобъекты, поэтому пример значений:

var dict = new Dictionary<string, string> { {"foo/bar/baz1", "123" }, {"foo/baz", "456" }, { "foo/abc", "def" } };

должен привести к:

{
     "foo": {
         "bar": {
             "baz1": "123"
         },
         "baz": "456",
         "abc": "def"
     }
}

При желании я хочу удалить кавычки вокруг "123" и "456" в вывод, если они могут быть интерпретированы как числа или логические значения.

Я использую Newtonsoft. JSON

1 Ответ

4 голосов
/ 15 марта 2020

Вы можете разобрать исходный словарь в JObject, используя метод JObject.FromObject. Затем go по всем свойствам разделите их, используя string.Split, и рекурсивно проанализируйте новый JObject, представляющий дерево свойств. Наконец, добавьте этот объект к целевому объекту, используя JObject.Add, или обновите его, если данный ключ уже существует

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)));
}

Он выдаст следующий вывод

{
  "foo": {
    "bar": {
      "baz1": "123"
    },
    "baz": "456",
    "abc": "def"
  }
}

Кроме того, приведенный выше код позволяет обрабатывать дерево свойств с любой глубиной. Я не думаю, что есть встроенный способ сериализации структуры, такой как foo/bar/baz1, в подобъекты в Json.NET

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...