使用appsettings.Production.json中的数据覆盖appsettings.json中的数组设置

lon*_*nix 7 c# asp.net-core asp.net-core-2.0

我正在使用ASP.NET Core 2.1.我有设置,appsettings.json并使用选项模式将它们绑定到类.我想覆盖它们中的一些appsettings.Production.json.

根据文档支持覆盖,并且通常对我有用.但它不适用于数组.

appsettings.json:

"MySectionOuter": {
  "MySectionInner": [
    {
      "foo": "1",
      "bar": "2",
      "baz": "3"
    },
    {
      "foo": "a",
      "bar": "b",
      "baz": "c"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我的重写 appsettings.Production.json

"MySectionOuter": {
  "MySectionInner": [
    {
      "bar": "4",
    },
    {
      "baz": "d"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

然而,这不起作用 - 它增加而不是替换.

读到该数组是键值存储的语法糖.所以我也试过这个:

"MySectionOuter": {
  "MySection:1": {
    "bar": "4",
  },
  "MySection:2": {
    "baz": "b",
  }
}
Run Code Online (Sandbox Code Playgroud)

但这也行不通.

什么是正确的语法?

UPDATE

评论显示我没有正确解释.我想要的是这样的:

在开发期间:

element1: foo=1
element1: bar=2
element1: baz=3
element2: foo=a
element2: bar=b
element2: baz=c
Run Code Online (Sandbox Code Playgroud)

生产期间:

element1: foo=1
element1: bar=2
element1: baz=4  // this was changed
element2: foo=a
element2: bar=b
element2: baz=d  // this was changed
Run Code Online (Sandbox Code Playgroud)

Phi*_*ohl 14

根据这篇博文:https : //www.paraesthesia.com/archive/2018/06/20/microsoft-extensions-configuration-deep-dive/

无法通过提供程序删除配置项。

您可以在覆盖时添加配置,但不能删除内容。您能做的最好的事情是用空字符串覆盖一个值。

相反,您应该只填写所需的少量信息,appsettings.config并在更专业的设置文件中填写适当的设置。例如appsettings.Development.config或您的appsettings.Production.config. 或者按照博客文章中的建议:

由于您无法删除内容,因此请尽可能少地指定配置,并在没有配置时使用代码中的默认值正确运行。

  • 问题是关于*替换*,而不是删除。只要 *key* 相同,替换就可以正常工作。对于数组,索引是键的一部分 (2认同)
  • @PanagiotisKanavos 问题要求在应用 `appsettings.production.config` 后,数组应该包含更少的元素。由于每个数组元素都有自己的键,它们必须从配置中_removed_。所以我认为答案仍然适用。 (2认同)

Max*_*ikh 10

实际上,构建配置时没有阵列.它只是一个键值对字典.所以你最终得到了字符串键,类似于 "mysectionouter:mysectioninner:0:foo" = 1.

因此,当您在配置中定义数组时,会发生以下情况:

appsettings.json:

"mysectionouter:mysectioninner:0:foo" = 1
"mysectionouter:mysectioninner:0:bar" = 2
Run Code Online (Sandbox Code Playgroud)

appsettings.production.json:

"mysectionouter:mysectioninner:0:bar" = new1
Run Code Online (Sandbox Code Playgroud)

结果:

foo = 1
bar = new1
Run Code Online (Sandbox Code Playgroud)

所以它只是基于索引,而下一个配置只是覆盖了一个键.在第二个示例中,除了更改索引之外,您什么也得不到.代表将是:

"mysectionouter:mysectioninner:1:bar" = new1
Run Code Online (Sandbox Code Playgroud)

回到你的问题:数组在appsettings中很棘手,虽然支持,但通常很难并且不直观.

通过索引,您可能会得到两个不相关对象的奇怪合并,如果您在文件中定义了不同的设置集,例如第一个配置中的设置A和B,以及第二个配置中的C,您将得到结果中的C和B,你可能根本不想要B.更糟糕的是,如果只定义每个对象的某些字段,则可以混合使用A和C.

我建议使用其他一些文件来存储这类信息.您还可以在配置加载的位置打破调试器,并亲自查看这些键是如何构建的,以获得更多洞察力.


Can*_*ale 5

当我尝试合并来自多个应用程序设置的数组时,当我偶然发现这个线程时,我实际上在 dotnet 6 中遇到了类似的问题。
解决方案实际上比想象的要简单得多。
Microsoft.Extensions.Configuration 通过索引合并数组:
{ foo: [1, 2, 3] } + { foo: [4, 5] } = { foo: 4, 5, 3 }

但我们希望能够声明哪些条目覆盖其他条目以及哪些条目应添加到列表中。我们通过将 GUID 声明为字典键而不是数组来实现此目的。

{
  "foo": {
     "870622cb-0372-49f3-a46e-07a1bd0db769": 1,
     "cbb3af55-94ea-41a5-bbb5-cb936ac47249": 2,
     "9410fcdc-28b3-4bff-bfed-4d7286b33294": 3
  }
}
+
{
  "foo": {
    "cbb3af55-94ea-41a5-bbb5-cb936ac47249": 4,
    "1c43fa78-b8db-41f8-809d-759a4bc35ee2": 5,
  }
}
=
{
  "foo": {
    "870622cb-0372-49f3-a46e-07a1bd0db769": 1,
    "cbb3af55-94ea-41a5-bbb5-cb936ac47249": 4, /*2 changed to 4 because key equals*/
    "9410fcdc-28b3-4bff-bfed-4d7286b33294": 3
    "1c43fa78-b8db-41f8-809d-759a4bc35ee2": 5, /*while 5 added to the list*/
  }
}
Run Code Online (Sandbox Code Playgroud)

一开始这可能看起来不方便,因为人们会认为, ((IConfiguration)config).GetSection("foo").Get<int[]>();

抛出某种无效类型异常,因为 Guid 不是我们所知的数组索引。但它实际上可以(隐式地!)将上面合并的“foo”部分返回为int[].