简体   繁体   English

牛顿JSON将复杂的密钥集合序列化为JSON

[英]Newton JSON serialize complex key collection into JSON

I have the below dictionary, and I need to convert the complex key values into proper JSON. 我有下面的字典,我需要将复杂的键值转换为正确的JSON。

static void Main(string[] args)
        {
            Dictionary<string, object> collectionProp = new Dictionary<string, object>();
            Dictionary<string, object> prop = new Dictionary<string, object>();
            prop.Add("content", "button");
            prop.Add("page.count", "10");
            prop.Add("columns.0.textAlign", "center");
            prop.Add("columns.1.textAlign", "left");
            var result = new Dictionary<string, object>();
            foreach (var pair in prop)
            {
                var key = pair.Key;                
                    var parts = key.Split('.');
                    var currentObj = result;
                    for (int i = 0; i < parts.Length - 1; i++)
                    {
                        var property = parts[i];
                        if (!currentObj.Keys.Contains(property))
                            currentObj[property] = new Dictionary<string, object>();
                        currentObj = (Dictionary<string, object>)currentObj[property];
                    }
                    currentObj[parts[parts.Length - 1]] = pair.Value;                
            }
            Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
            Console.ReadLine();
        }

And getting the following result. 并得到以下结果。

{
  "content": "button",
  "page": {
    "count": "10"
  },
  "columns": {
    "0": {
      "textAlign": "center"
    },
    "1": {
      "textAlign": "left"
    }
  }
}

Expecting the columns should be grouped as JSON array. 期望这些列应分组为JSON数组。 How to achieve this.? 如何实现这一目标?

The desired output: 所需的输出:

{
  "content": "button",
  "page": {
    "count": "10"
  },
  "columns": [
    {
      "textAlign": "center"
    },
    {
      "textAlign": "left"
    }
  ]
}

JSON.NET will serialize dictionaries as JSON objects by default even though its keys are convertible to an integer. JSON.NET默认会将字典序列化为JSON对象,即使其键可以转换为整数。 Instead of building a dictionary from the source you could build JObject hierarchy. 代替从源头构建字典,您可以构建JObject层次结构。 These helper methods recognize array indices indices in your path to automatically build JArray container around them: 这些帮助器方法可以识别路径中的数组索引索引,以围绕它们自动构建JArray容器:

public static class JsonExtensions
{
    public static void SetValue(this JContainer container, string path, object value)
    {
        JToken token = container;
        var keys = path.Split('.');
        foreach (var key in keys)
        {
            int index;
            if (int.TryParse(key, out index))
            {
                var jArray = token as JArray;
                if (jArray == null)
                {
                    jArray = new JArray();
                    token.Replace(jArray);
                    token = jArray;
                }
                while (index >= jArray.Count)
                {
                    jArray.Add(JValue.CreateNull());
                }
                token = jArray[index];
            }
            else
            {
                var jObject = token as JObject;
                if (jObject == null)
                {
                    jObject = new JObject();
                    token.Replace(jObject);
                    token = jObject;
                }
                token = token[key] ?? (token[key] = JValue.CreateNull());
            }
        }
        token.Replace(new JValue(value));
    }

    public static void SetValues(this JContainer container, IEnumerable<KeyValuePair<string, object>> pairs)
    {
        foreach (var pair in pairs)
        {
            container.SetValue(pair.Key, pair.Value);
        }
    }
}

And here's how you get the results you expect: 这就是您获得期望结果的方式:

var jObject = new JObject();
jObject.SetValues(new Dictionary<string, object>
{
    { "content", "button" },
    { "page.count", "10" },
    { "columns.0.textAlign", "center" },
    { "columns.1.textAlign", "left" }
});
Console.WriteLine(jObject.ToString(Formatting.Indented));

Note that the code sample I provided is no way near efficient and should be used just as an inspiration to achieve the result you require. 请注意,我提供的代码示例效率不高,应将其用作获得所需结果的灵感。

Also note that in some cases the order of values to build the JObject matters, but enumerating items from dictionary is non-deterministic . 还要注意,在某些情况下,构建JObject的值顺序JObject重要,但是从dictionary枚举项目是不确定的 Therefore you might consider a better data structure for the source that guarantees order of key-value pairs in it such as an array. 因此,您可能会考虑为源提供更好的数据结构,以保证键值对在其中的顺序,例如数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM