解决此问题的一种方法是手工制作JObjects,然后将它们合并。 (这不是最高效的解决方案,因为它会多次重新创建层次结构的某些级别。)
这种方法不同于Benzara Tahar 提出的解决方案:
- Tahar:使用字符串操作来构造一个有效的 json,然后使用
Json.Parse
- 我的:使用路径遍历来构造
JObject 层次结构。
核心逻辑
核心逻辑可以这样实现:
static JObject CreateHierarchy(Queue<string> pathLevels, JObject currentNode)
{
if (pathLevels.Count == 0) return currentNode;
var newNode = new JObject(new JProperty(pathLevels.Dequeue(), currentNode));
return CreateHierarchy(pathLevels, newNode);
}
- 这是一个递归函数,它构建从最内层到最外层的层次结构。
- 因此,如果我们使用以下
pathLevels 调用此方法:data, buyerDecision, data, myDescision
那么它会生成这样的东西:
new JObject(
new JProperty("myDecision",
new JObject(
new JProperty("data",
new JObject(
new JProperty("buyerDecision",
new JObject(
new JProperty("data", currentNode)))))));
调用核心逻辑
首先,将输入字符串转换成字典,其中
var dataSource = new List<string>
{
"myDecision/data/buyerDecision/data/buy = food",
"myDecision/data/sellerDecision/data/sell = food"
};
var mappings = dataSource.Select(data => data.Split('=', StringSplitOptions.RemoveEmptyEntries))
.ToDictionary(parts => parts[0].Trim(), parts => parts[1].Trim());
-
注意:这很脆弱,因为如果多个数据源条目想要设置相同的属性,它可能会抛出
ArgumentException: 'An item with the same key has already been added。
- 我们可以遍历字典,从条目中构造
JObjects
- 密钥应该被
/拆分然后反向集合
- 最里面的值和最里面的路径可以用来构造
currentNode
var objectsWithHierarchy = new List<JObject>();
foreach (var (path, innerMostValue) in mappings.Select(kv => (kv.Key, kv.Value)))
{
var entryLevels = path.Split('/').Reverse().ToArray();
objectsWithHierarchy.Add(CreateHierarchy(new Queue<string>(entryLevels.Skip(1)),
new JObject(new JProperty(entryLevels.First(), innerMostValue))));
}
合并对象
在这里,我们从objectsWithHierarchy 中选择第一个对象作为集合的基础JObject,我们在此基础上应用/合并JObjects 的其余部分。
var baseObject = objectsWithHierarchy.First();
var mergeSettings = new JsonMergeSettings {MergeArrayHandling = MergeArrayHandling.Union};
foreach (var currentObj in objectsWithHierarchy.Skip(1))
{
baseObject.Merge(currentObj, mergeSettings);
}
Console.WriteLine(baseObject);
输出如下:
{
"myDecision": {
"data": {
"buyerDecision": {
"data": {
"buy": "food"
}
},
"sellerDecision": {
"data": {
"sell": "food"
}
}
}
}
}
结束的想法
- 这段代码真的很脆弱,因为它是根据两个样本数据设计的,没有实际要求
- 数据格式非常独特,所以我们想使用JSONPath之类的东西
- 实际用例也是未知的,因此解决方案本身的性能可能很差