如何基于JObject属性检索多层数组并构建查询字典
自定义属性图层与要素映射解决方案
输入JSON结构
{ "Layers": [ { "Name": "Layer 1", "Features": [ { "Name": "Feature 1", "Properties": { "Custom property A": "someValue", "Custom property B": "someValue" } }, { "Name": "Feature 2", "Properties": { "Custom property A": "someValue", "Custom property B": "someValue" } } ] }, { "Name": "Layer 2", "Features": [ { "Name": "Feature 1", "Properties": { "Custom property A": "someValue", "Custom property B": "someValue" } }, { "Name": "Feature 2", "Properties": { "Custom property A": "someValue", "Custom property B": "someValue" } } ] } ] }
反序列化后的.NET类结构
public class Data { public List<Layer> Layers { get; set; } } public class Layer { public string Name { get; set; } public List<Feature> Features { get; set; } } public class Feature { public string Name { get; set; } public JObject Properties { get; set; } // 自定义属性为JObject,支持动态键值 }
需求目标
根据用户输入的自定义属性名,检索该属性所在的图层(Layer)及对应要素(Feature),示例输出如下:
The Custom property A is used in: Layer 1 Feature 1 Feature 2 Layer 2 Feature 1 Feature 2
已完成步骤:获取所有唯一自定义属性
通过LINQ提取所有不重复的自定义属性名:
List<string> allProps = _data.Layers.SelectMany(layer => layer.Features) .SelectMany(feature => feature.Properties.Properties().Select(jProperty => jProperty.Name)) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList();
解决方案:构建属性映射字典
我们需要将每个自定义属性映射到其所在的图层及对应的要素列表,生成Dictionary<string, Dictionary<string, List<string>>>类型的字典(顶层键为属性名,中层键为图层名,值为要素名列表)。以下提供两种实现方式:
方式一:LINQ实现
利用嵌套GroupBy直接构建映射字典,代码简洁:
var propertyMap = _data.Layers .SelectMany(layer => layer.Features .SelectMany(feature => feature.Properties.Properties() .Select(prop => new { PropName = prop.Name, LayerName = layer.Name, FeatureName = feature.Name }))) // 按属性名分组(忽略大小写) .GroupBy(x => x.PropName, StringComparer.OrdinalIgnoreCase) .ToDictionary( g => g.Key, g => g.GroupBy(x => x.LayerName) .ToDictionary( lg => lg.Key, lg => lg.Select(x => x.FeatureName).Distinct().ToList() ), StringComparer.OrdinalIgnoreCase );
方式二:循环遍历实现
适合大文件场景,内存占用更可控,逻辑直观:
// 顶层字典:属性名 -> 图层名 -> 要素列表(忽略大小写比较) var propertyMap = new Dictionary<string, Dictionary<string, List<string>>>(StringComparer.OrdinalIgnoreCase); foreach (var layer in _data.Layers) { foreach (var feature in layer.Features) { foreach (var prop in feature.Properties.Properties()) { string propName = prop.Name; // 初始化属性对应的图层字典 if (!propertyMap.ContainsKey(propName)) { propertyMap[propName] = new Dictionary<string, List<string>>(); } var layerDict = propertyMap[propName]; // 初始化图层对应的要素列表 if (!layerDict.ContainsKey(layer.Name)) { layerDict[layer.Name] = new List<string>(); } var featureList = layerDict[layer.Name]; // 避免重复添加同一要素 if (!featureList.Contains(feature.Name)) { featureList.Add(feature.Name); } } } }
使用映射字典查询属性
构建完成后,即可快速查询任意属性的分布:
string targetProperty = "Custom property A"; if (propertyMap.TryGetValue(targetProperty, out var layerFeatureMap)) { Console.WriteLine($"The {targetProperty} is used in:"); foreach (var layerEntry in layerFeatureMap) { Console.WriteLine(layerEntry.Key); foreach (var featureName in layerEntry.Value) { Console.WriteLine($" {featureName}"); } } } else { Console.WriteLine($"The {targetProperty} was not found in any features."); }
内容的提问来源于stack exchange,提问作者3AgL3 DeeJay
相关产品推荐
相关产品推荐

