我如何将注明的名称空间字符串的列表对嵌套的JSON字符串进行排序?
类似的东西。
var string1 = "example.string.1";
var string2 = "example.string.2";
var string3 = "example.anotherstring.1";
整理了这个。
{
"example": {
"string": ["1", "2"],
"anotherstring": ["1"]
}
}
编辑1
谢谢!我能够使用您的答案接近工作。
在此列表中,它有效:
var strings = new List<string>
{
"example.string.1",
"example.string.2",
"example.anotherstring.1",
};
public void Example()
{
var dict = new Dictionary<string, dynamic>();
foreach (var s in strings)
{
AddPartsToDictionary(dict, s.Split('.'));
}
}
public void AddPartsToDictionary(IDictionary<string, dynamic> dict, string[] parts)
{
for (var i = 0; i < parts.Length; i++)
{
if (i < parts.Length - 2)
{
if (!dict.ContainsKey(parts[i]))
dict.Add(parts[i], new Dictionary<string, dynamic>());
dict = dict[parts[i]];
}
else if (i < parts.Length - 1)
{
if (!dict.ContainsKey(parts[i]))
{
var list = new List<string>();
dict[parts[i]] = list;
}
}
else
{
var list = dict[parts[i - 1]] as List<string>;
list.Add(parts[i]);
}
}
}
结果JSON
{
"example": {
"string": [
"1",
"2"
],
"anotherstring": [
"1"
]
}
}
在此列表中,它失败了
var strings = new List<string>
{
"example.string.1",
"example.string.example.1",
"example.string.2",
"example.anotherstring.1",
"example.string.example.2",
"string.example.2"
};
我可能必须对列表或其他内容进行排序,但仍在努力。希望这有助于弄清楚它。
对象一直向下
如果使用对象(代替数组(一直都可以,则可以正常工作。
var strings = new List<string> {
"example.string.1",
"example.string.2",
"example.anotherstring.1",
};
var result = strings.Aggregate(new Dictionary<string, Object>(), (acc, s) =>
{
var level = acc;
foreach(var segment in s.Split('.'))
{
if (!level.ContainsKey(segment))
{
var child = new Dictionary<string, Object>();
level.Add(segment, child);
}
level = level[segment] as Dictionary<string, Object>;
}
return acc;
});
var json = JsonConvert.SerializeObject(result, Formatting.Indented);
输出一直都有对象。
{
"example": {
"string": {
"1": {},
"2": {}
},
"anotherstring": {
"1": {}
}
}
}
在最后级别(带小提琴(
如果您想在最后级别进行数组,那么我们需要对定义最后一个级别的确切定义。例如,最后一个级别是否总是包含整数?如果是这样,以下有效。
var result = strings.Aggregate(new Dictionary<string, Object>(), (acc, s) =>
{
Dictionary<string, Object> previousLevel = null;
Dictionary<string, Object> nextLevel = acc;
string previousSegment = null;
foreach (string nextSegment in s.Split('.'))
{
if (Int16.TryParse(nextSegment, out _))
{
if (previousLevel[previousSegment] is Dictionary<string, Object>)
{
previousLevel[previousSegment] = new List<string>();
}
var list = previousLevel[previousSegment] as List<string>;
list.Add(nextSegment);
}
else
{
if (!nextLevel.ContainsKey(nextSegment))
{
var child = new Dictionary<string, Object>();
nextLevel.Add(nextSegment, child);
}
previousSegment = nextSegment;
previousLevel = nextLevel;
nextLevel = nextLevel[nextSegment] as Dictionary<string, Object>;
}
}
return acc;
});
输出在最后级别。
{
"example": {
"string": [
"1",
"2"
],
"anotherstring": [
"1",
"2"
]
}
}
此数组版本仅在最后一个级别仅是integer
类型的情况下才能工作,这是您最初的问题所需的。
更困难的情况是在同一级别上处理混合的string
和integer
类型,该级别的输入看起来像这样:
"System.1",
"System.2",
"System.Collections.1",
"System.Collections.2",
"System.Collections.Generic.1"
需要更复杂的算法。如果这是隐藏的要求,请考虑在此答案的评论中提出一个全新的后续问题并链接到它。
我以为id快速地走了,它接近但不是您想要的。但是我认为这可能会激发您或其他人尝试。
免责声明,我不是真正的 json.net aficionado,此代码是 相当不错。不寻常,至少要说
演示此处
给定列表
var list = new List<string>
{
"example.string.1",
"example.string.2",
"example.anotherstring.1",
"example.anotherstring.2",
"System",
"System.Diagnostics",
"System.Text",
"System.Collections.Generic",
"System.Linq",
"System.Diagnostics.1",
"System.Text.1",
"System.Collections.Generic.1",
"System.Linq.1",
"System.Diagnostics.2",
"System.Text.2",
"System.Collections.Generic.2",
"System.Linq.2"
};
一些类
public class RawValue
{
public RawValue(string key, IEnumerable<IEnumerable<string>> values)
{
Key = key;
Values = values;
}
public string Key { get; set; }
public IEnumerable<IEnumerable<string>> Values { get; set; }
}
public class NameSpace : Dictionary<string, NameSpace>
{
}
一些帮助者
private static IEnumerable<RawValue> GetRawValues(RawValue value)
{
return value.Values.Where(x => x.Any())
.GroupBy(x => x.FirstOrDefault())
.Select(x => new RawValue(x.Key, x.Select(y => y.Skip(1))));
}
private static NameSpace GroupNameSpaces(IEnumerable<RawValue> groups)
{
var result = new NameSpace();
foreach (var group in groups)
result.Add(group.Key, GroupNameSpaces(GetRawValues(group)));
return result;
}
主代码
var groups = list.Select(x => x.Split('.'))
.GroupBy(x => x.FirstOrDefault())
.Select(x => new RawValue(x.Key, x.Select(y => y.Skip(1))));
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
var result = GroupNameSpaces(groups);
var json = JsonConvert.SerializeObject(result, Formatting.Indented, settings);
Console.WriteLine(json);
输出
{
"example": {
"string": {
"1": {},
"2": {}
},
"anotherstring": {
"1": {},
"2": {}
}
},
"System": {
"Diagnostics": {
"1": {},
"2": {}
},
"Text": {
"1": {},
"2": {}
},
"Collections": {
"Generic": {
"1": {},
"2": {}
}
},
"Linq": {
"1": {},
"2": {}
}
}
}
我认为由于我不知道如何在 json.net 中更好地序列化的事实,我的失败必须使用NameSpace : Dictionary<string, NameSpace>
。同样,我不花时间在此上,我无法弄清楚如何将最后一个节点转换为JSON数组。尽管我不确定您是否可以考虑。但是我确定可以做得更好