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

Posted

技术标签:

【中文标题】用 appsettings.Production.json 中的设置覆盖 appsettings.json 中的数组设置【英文标题】:Override array settings in appsettings.json with those in appsettings.Production.json 【发布时间】:2019-03-16 05:44:06 【问题描述】:

我正在使用 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"
    
  ]

我在appsettings.Production.json 中的覆盖

"MySectionOuter": 
  "MySectionInner": [
    
      "bar": "4",
    ,
    
      "baz": "d"
    
  ]

但这不起作用 - 它是添加而不是替换。

我read that 数组是键值存储的语法糖。所以我也尝试了这个:

"MySectionOuter": 
  "MySection:1": 
    "bar": "4",
  ,
  "MySection:2": 
    "baz": "b",
  

但这也行不通。

正确的语法是什么?

更新

cmets 显示我没有正确解释。我想要的是这样的:

在开发过程中:

element1: foo=1
element1: bar=2
element1: baz=3
element2: foo=a
element2: bar=b
element2: baz=c

制作过程中:

element1: foo=1
element1: bar=2
element1: baz=4  // this was changed
element2: foo=a
element2: bar=b
element2: baz=d  // this was changed

【问题讨论】:

为什么要使用 array,尤其是在内容不相关的情况下?除了难以覆盖值之外,您不能将内容读入 List 或任何其他类型的强类型容器。您必须阅读各个值。 此外,配置设置中没有无订单保证。提供者(例如数据库提供者)可以以任何顺序返回它们,并且配置将(应该)仍然以相同的方式工作。 JSON层次结构仅用于生成密钥路径,仅此而已 感谢您指出这一点 - 这只是一个示例,我已经对其进行了更改。 @Ionix 答案还是一样的。 Everything 是通向价值观的路径。马克西姆解释了它是如何工作的。您的第二个示例仅覆盖 MySectionOuter::MySection:1::barMySectionOuter::MySection:2::baz,而不是其他值。将 1 放在名称中并没有改变这一点。 @Ionix 就基于文件的提供程序而言,您可以依赖于顺序。如果您添加另一个提供程序,例如数据库,您必须确保有 something 可用于重建完整密钥。数据库可以按任何顺序返回结果。如果数据库记录包含 Index 字段,您可以使用它来构建由文件生成的相同设置路径。 【参考方案1】:

实际上,在构建配置时,那里并没有数组。它只是一个键值对字典。所以你最终得到了字符串键,比如 "mysectionouter:mysectioninner:0:foo" = 1.

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

appsettings.json:

"mysectionouter:mysectioninner:0:foo" = 1
"mysectionouter:mysectioninner:0:bar" = 2

appsettings.production.json:

"mysectionouter:mysectioninner:0:bar" = new1

结果:

foo = 1
bar = new1

所以它只是基于索引的,下一个配置只是覆盖一个键。在您的第二个示例中,除了更改索引之外,您什么也没做。表示将是:

"mysectionouter:mysectioninner:1:bar" = new1

回到你的问题:数组在应用程序设置中很棘手,虽然受支持,但通常很难使用且不直观。

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

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

【讨论】:

【参考方案2】:

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

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

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

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

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

【讨论】:

问题是关于替换,而不是删除。只要 key 相同,替换就可以了。对于数组,索引是键的一部分 @PanagiotisKanavos 问题要求在应用appsettings.production.config 之后数组应该包含更少的元素。由于每个数组元素都有自己的键,因此必须将它们从配置中删除。所以我认为答案仍然适用。 数组包含相同数量的元素。正是那些 elements 虽然具有较少的属性。 OP假设数组或元素本身将被替换。可能没有意识到只有设置本身很重要,其他一切都只是通往价值观的途径 你是对的!我会留下答案,因为博客文章中的建议仍然有意义 - 应用后问题就会消失。 这很好地为我修复了它。我只是在根文件中将这些数组设置留空。完美!

以上是关于用 appsettings.Production.json 中的设置覆盖 appsettings.json 中的数组设置的主要内容,如果未能解决你的问题,请参考以下文章

发布未从 appsettings.production.json 获取连接字符串

asp.net core 1 appsettings.production.json 不更新连接字符串

IoTSharp部署教程-Sqlite分表篇

故障公告新版博客后台部署时的配置问题引发故障

测试用。

测试用例(功能用例)——完整demo(一千多条测试用例)