为何GetSection("XPaths").GetChildren()返回排序后的子节点列表?
解决JSON配置节点读取顺序与原始文件不一致的问题
问题原因
- .NET的
ConfigurationBuilder解析JSON配置时,默认会按键名排序返回子节点,这是框架内部的处理逻辑。 - 最终转换为
Dictionary<string, string?>时,传统Dictionary(.NET Core 3.0之前)本身不保留插入顺序,会进一步打乱原始顺序。
解决方案
要保留JSON文件的原始属性顺序,可通过以下两种方式实现:
方案1:直接读取JSON并按原始顺序解析
绕过配置系统的排序逻辑,直接用JSON序列化库读取文件并遍历原始属性:
using System.Text.Json; using System.Collections.Specialized; public static OrderedDictionary GetXpaths(string form) { var xPaths = new OrderedDictionary(); try { form = !File.Exists($"{form}.json") ? $"{(int)FormToGetXpaths.Default}" : form; string jsonPath = Path.Combine(Directory.GetCurrentDirectory(), $"{form}.json"); string jsonContent = File.ReadAllText(jsonPath); using JsonDocument doc = JsonDocument.Parse(jsonContent); JsonElement xPathsSection = doc.RootElement.GetProperty("XPaths"); // 按JSON原始顺序遍历属性 foreach (JsonProperty prop in xPathsSection.EnumerateObject()) { xPaths.Add(prop.Name, prop.Value.GetString()); } } catch (Exception ex) { Console.WriteLine($"Failed to get XPaths for {form}\n{ex.Message}"); } return xPaths; }
方案2:配置系统开启保留属性顺序(.NET 6+专属)
.NET 6及以上版本的JsonConfigurationSource提供了PreservePropertyOrder选项,开启后可保留JSON原始顺序:
public static List<KeyValuePair<string, string?>> GetXpaths(string form) { var xPaths = new List<KeyValuePair<string, string?>>(); try { form = !File.Exists($"{form}.json") ? $"{(int)FormToGetXpaths.Default}" : form; var xPathbuilder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile(options => { options.Path = $"{form}.json"; options.Optional = true; options.ReloadOnChange = true; // 启用保留属性顺序 options.PreservePropertyOrder = true; }); var _xpathconfiguration = xPathbuilder.Build(); // 此时GetChildren()会按JSON原始顺序返回 xPaths = _xpathconfiguration.GetSection("XPaths") .GetChildren() .Select(x => new KeyValuePair<string, string?>(x.Key, x.Value)) .ToList(); } catch (Exception ex) { Console.WriteLine($"Failed to get XPaths for {form}\n{ex.Message}"); } return xPaths; }
关键提示
- 若要生成Excel,建议返回
List<KeyValuePair<string, string?>>或OrderedDictionary,避免使用普通Dictionary,防止顺序意外变更。 - .NET Framework或.NET Core 3.0以下版本不支持方案2,只能采用方案1直接读取JSON。
内容的提问来源于stack exchange,提问作者Dreamer
相关产品推荐
相关产品推荐

