.NET应用如何加载多个 appsettings.json 文件

2025-03-18#.NET#C#

在 .NET 应用中,通常使用 appsettings.json 文件存储应用的配置信息。对于有多个环境的项目,通常还会针对每个环境,再创建一个 appsettings.{Environment}.json 用于存储特定于每个环境的配置,比如 appsettings.Development.jsonappsettings.Production.json 等。然后,可以在代码中,加载并合并 appsettings.jsonappsettings.{Environment}.json。对于简单的值为字符串类型的配置,合并规则简单明了:直接覆盖即可。但是,如果配置项是复杂结构,比如嵌套的字典和数组,那么合并多个配置文件时,是什么规则呢?

简单地说:对于嵌套的字典,那么根据字典的键逐层进行覆盖或者增加;而数组其实是被当作字典对待的,数组的索引是键的一部分,然后按照字典的规则进行合并。

下面通过简单的代码进行演示。

代码示例 🔗

首先创建一个C#的 .NET 控制台程序,并且安装处理配置的包 Microsoft.Extensions.Configuration.Json。同时将 appsettings.jsonappsettings.Development.json 文件添加到项目文件清单中。最终,csproj 文件的内容为:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
    <Content Include="appsettings.json;appsettings.Development.json">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

</Project>

程序代码文件 Program.cs 的内容为:

using Microsoft.Extensions.Configuration;

class Program
{
    static void Main()
    {
        var configuration = new ConfigurationBuilder()
           .SetBasePath(AppContext.BaseDirectory)
           .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
           .AddJsonFile($"appsettings.Development.json", optional: false, reloadOnChange: true)
           .Build();

        foreach (var item in configuration.AsEnumerable())
        {
            Console.WriteLine($"{item.Key} -> {item.Value}");
        }
    }
}

从代码中可以看出,其实每个配置项(即 item )都是键值对,其类型为 KeyValuePair<string, string?>

appsettings.json 内容如下:

{
    "Transforms": [
        { "RequestHeaderOriginHost": "true" }
    ]
}

appsettings.Development.json 的内容如下:

{
    "Transforms": [
        { "PathRemovePrefix": "/prefix" },
        { "RequestHeaderOriginHost": "false" }
    ]
}

运行结果 🔗

构建和运行应用,控制台输出为:

Transforms -> 
Transforms:1 -> 
Transforms:1:RequestHeaderOriginHost -> false
Transforms:0 -> 
Transforms:0:RequestHeaderOriginHost -> true
Transforms:0:PathRemovePrefix -> /prefix

如果将其还原成 JSON 格式,那么就得到合并后的 JSON,其实为:

{
	"Transforms": [
		{"RequestHeaderOriginHost": "true", "PathRemovePrefix": "/prefix"},
		{"RequestHeaderOriginHost": "false"}
	]
}

这可能并不是期望的结果。

从控制台的输出,还可以看到:在迭代每个配置项时,对于值为数组的元素,并没有按照数组下标遍历。而是先输出第二个元素(即 Transforms:1 ),再输出第一个元素(即 Transforms:0)。


加载中...