我有下面的字典,我需要将复杂的键值转换为正确的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();
}
并获得以下结果。
{
"content": "button",
"page": {
"count": "10"
},
"columns": {
"0": {
"textAlign": "center"
},
"1": {
"textAlign": "left"
}
}
}
期望列应分组为JSON数组。如何实现这一目标??
所需的输出:
{
"content": "button",
"page": {
"count": "10"
},
"columns": [
{
"textAlign": "center"
},
{
"textAlign": "left"
}
]
}
答案 0 :(得分:1)
JSON.NET默认将字典序列化为JSON对象,即使其键可转换为整数也是如此。代替从源头构建字典,您可以构建JObject
层次结构。这些帮助器方法可以识别路径中的数组索引索引,从而自动围绕它们建立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);
}
}
}
这是您获得期望结果的方式:
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));
请注意,我提供的代码示例效率不高,应将其用作获得所需结果的灵感。
还要注意,在某些情况下,构建JObject
的值顺序很重要,但enumerating items from dictionary is non-deterministic却很重要。因此,您可能会考虑为源保证更好的数据结构,以保证键值对在其中的顺序(例如数组)。