如何将带有点符号和数组的字符串转换为 json?
How can I convert a string with dot notation and arrays to json?
我正在尝试将点表示法的字符串转换为 JSON。
例如,在 Dictionary<string, object>
中,我有以下键值对:
key: "resource.person[0].name"
value: "bob"
key: "resource.person[1].name"
value: "dylan"
我有以下代码可以将键的点表示法转换为 JSON 但它会忽略数组:
var formattedDictionary = new Dictionary<string, object>();
foreach(var pair in returnFields)
{
var key = pair.Key;
var parts = key.Split('.');
var currentObj = formattedDictionary;
for (int i = 0; i < parts.Length-1; i++)
{
var property = parts[i];
if (!currentObj.ContainsKey(property))
currentObj[property] = new Dictionary<string, object>();
currentObj = (Dictionary<string, object>)currentObj[property];
}
currentObj[parts[^1]] = pair.Value;
}
return formattedDictionary;
目前Return秒:
{
"resource": {
"person[0]": {
"name" : "bob"
},
"person[1]": {
"name" : "dylan"
}
}
}
我需要一些帮助来修改上面的代码,以便也处理数组给我一个看起来像这样的输出
理想Return:
{
"resource": {
"person": [
{
"name" : "bob"
},
{
"name" : "dylan"
}
]
}
}
谢谢!
也许像
var formattedDictionary = new Dictionary<string, object>();
foreach (var pair in returnFields)
{
var key = pair.Key;
var parts = key.Split('.');
var currentObj = formattedDictionary;
for (int i = 0; i < parts.Length - 1; i++)
{
var property = parts[i];
int index = -1;
//naive handle arrays
if (property.Contains('['))
{
var bits = property.Split('[', ']');
property = bits[0];
index = int.Parse(bits[1]);
}
if (!currentObj.ContainsKey(property))
{
//is it an array
if (index > -1)
{
//make a list of dictionaries instead of just one
var list = new List<Dictionary<string, object>>();
currentObj[property] = list;
//ensure there are enough list entries for us to access the list by index without it going boom
while (list.Count <= index)
list.Add(new Dictionary<string, object>());
//"travel" to the current obj being the list item, at index whatever
currentObj = (Dictionary<string, object>)list[index];
}
else {
currentObj[property] = new Dictionary<string, object>();
currentObj = (Dictionary<string, object>)currentObj[property];
}
}
}
currentObj[parts[^1]] = pair.Value;
}
我还没有测试过,但它基本上将“创建一个新的子字典”扩展为“如果它包含一个索引器,那么它必须是一个列表,所以确保有一个足够大的列表来容纳它,并改为前往该列表索引
请注意,formattedDictionary 中的对象不再总是字符串或字典。它现在有时也可能是 List<Dictionary>
这对我有用(使用递归)
private static Dictionary<string, object> CheckAndCreateKey(string key, object value, Dictionary<string, object> dict)
{
if (!key.Contains("."))
{
dict[key] = value;
return dict;
}
var firstLevel = key.Split('.')[0];
var remainingParts = key.Replace(firstLevel + ".", "");
var index = -1;
if (firstLevel.Contains("["))
{
var bits = firstLevel.Split('[', ']');
firstLevel = bits[0];
index = int.Parse(bits[1]);
}
if (!dict.ContainsKey(firstLevel))
{
// new property
var nestedDict = CheckAndCreateKey(remainingParts, value, new Dictionary<string, object>());
if (index > -1)
{
// this is an Array
var list = new List<Dictionary<string, object>>();
while (list.Count <= index) // add require length, in case when index are in the wrong order (e.g. cars[1].make appears first before cars[0].make)
list.Add(new Dictionary<string, object>());
list[index] = nestedDict;
dict[firstLevel] = list;
return dict;
}
dict[firstLevel] = nestedDict;
return dict;
}
if (index > -1)
{
var list = (List<Dictionary<string, object>>) dict[firstLevel];
while (list.Count <= index) // add missing items
list.Add(new Dictionary<string, object>());
var nestedDict = CheckAndCreateKey(remainingParts, value, (Dictionary<string, object>) list[index]);
dict[firstLevel] = list;
return dict;
}
var current = (Dictionary<string, object>) dict[firstLevel];
dict[firstLevel] = CheckAndCreateKey(remainingParts, value, current);
return dict;
}
public static Dictionary<string, object> ParseDotNotation(this Dictionary<string, object> input)
{
var formattedDictionary = new Dictionary<string, object>();
foreach (var pair in input)
{
CheckAndCreateKey(pair.Key, pair.Value, formattedDictionary);
}
return formattedDictionary;
}
我正在尝试将点表示法的字符串转换为 JSON。
例如,在 Dictionary<string, object>
中,我有以下键值对:
key: "resource.person[0].name"
value: "bob"
key: "resource.person[1].name"
value: "dylan"
我有以下代码可以将键的点表示法转换为 JSON 但它会忽略数组:
var formattedDictionary = new Dictionary<string, object>();
foreach(var pair in returnFields)
{
var key = pair.Key;
var parts = key.Split('.');
var currentObj = formattedDictionary;
for (int i = 0; i < parts.Length-1; i++)
{
var property = parts[i];
if (!currentObj.ContainsKey(property))
currentObj[property] = new Dictionary<string, object>();
currentObj = (Dictionary<string, object>)currentObj[property];
}
currentObj[parts[^1]] = pair.Value;
}
return formattedDictionary;
目前Return秒:
{
"resource": {
"person[0]": {
"name" : "bob"
},
"person[1]": {
"name" : "dylan"
}
}
}
我需要一些帮助来修改上面的代码,以便也处理数组给我一个看起来像这样的输出
理想Return:
{
"resource": {
"person": [
{
"name" : "bob"
},
{
"name" : "dylan"
}
]
}
}
谢谢!
也许像
var formattedDictionary = new Dictionary<string, object>();
foreach (var pair in returnFields)
{
var key = pair.Key;
var parts = key.Split('.');
var currentObj = formattedDictionary;
for (int i = 0; i < parts.Length - 1; i++)
{
var property = parts[i];
int index = -1;
//naive handle arrays
if (property.Contains('['))
{
var bits = property.Split('[', ']');
property = bits[0];
index = int.Parse(bits[1]);
}
if (!currentObj.ContainsKey(property))
{
//is it an array
if (index > -1)
{
//make a list of dictionaries instead of just one
var list = new List<Dictionary<string, object>>();
currentObj[property] = list;
//ensure there are enough list entries for us to access the list by index without it going boom
while (list.Count <= index)
list.Add(new Dictionary<string, object>());
//"travel" to the current obj being the list item, at index whatever
currentObj = (Dictionary<string, object>)list[index];
}
else {
currentObj[property] = new Dictionary<string, object>();
currentObj = (Dictionary<string, object>)currentObj[property];
}
}
}
currentObj[parts[^1]] = pair.Value;
}
我还没有测试过,但它基本上将“创建一个新的子字典”扩展为“如果它包含一个索引器,那么它必须是一个列表,所以确保有一个足够大的列表来容纳它,并改为前往该列表索引
请注意,formattedDictionary 中的对象不再总是字符串或字典。它现在有时也可能是 List<Dictionary>
这对我有用(使用递归)
private static Dictionary<string, object> CheckAndCreateKey(string key, object value, Dictionary<string, object> dict)
{
if (!key.Contains("."))
{
dict[key] = value;
return dict;
}
var firstLevel = key.Split('.')[0];
var remainingParts = key.Replace(firstLevel + ".", "");
var index = -1;
if (firstLevel.Contains("["))
{
var bits = firstLevel.Split('[', ']');
firstLevel = bits[0];
index = int.Parse(bits[1]);
}
if (!dict.ContainsKey(firstLevel))
{
// new property
var nestedDict = CheckAndCreateKey(remainingParts, value, new Dictionary<string, object>());
if (index > -1)
{
// this is an Array
var list = new List<Dictionary<string, object>>();
while (list.Count <= index) // add require length, in case when index are in the wrong order (e.g. cars[1].make appears first before cars[0].make)
list.Add(new Dictionary<string, object>());
list[index] = nestedDict;
dict[firstLevel] = list;
return dict;
}
dict[firstLevel] = nestedDict;
return dict;
}
if (index > -1)
{
var list = (List<Dictionary<string, object>>) dict[firstLevel];
while (list.Count <= index) // add missing items
list.Add(new Dictionary<string, object>());
var nestedDict = CheckAndCreateKey(remainingParts, value, (Dictionary<string, object>) list[index]);
dict[firstLevel] = list;
return dict;
}
var current = (Dictionary<string, object>) dict[firstLevel];
dict[firstLevel] = CheckAndCreateKey(remainingParts, value, current);
return dict;
}
public static Dictionary<string, object> ParseDotNotation(this Dictionary<string, object> input)
{
var formattedDictionary = new Dictionary<string, object>();
foreach (var pair in input)
{
CheckAndCreateKey(pair.Key, pair.Value, formattedDictionary);
}
return formattedDictionary;
}