Заменить настройки массива в appsettings.json настройками в appsettings.Production.json

Я использую 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"
    }
  ]
}

Однако это не работает - он скорее добавляет, чем заменяет.

Я прочтите это массив является синтаксическим сахаром для хранилища значений ключей. Итак, я также попробовал это:

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

Но это тоже не работает.

Какой правильный синтаксис?

ОБНОВИТЬ

Комментарии показывают, что я не объяснил должным образом. Я хочу вот что:

В процессе разработки:

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

Зачем вообще использовать множество, особенно когда содержимое не связано? Помимо того, что трудно переопределить значения, вы не можете прочитать содержимое в List <T> или любом другом строго типизированном контейнере. Вам нужно будет прочитать отдельные значения.

Panagiotis Kanavos 11.10.2018 10:22

Кроме того, в настройках конфигурации есть нет гарантии заказа. Провайдер (например, провайдер базы данных) может возвращать их в любом порядке, и конфигурация будет (должна) по-прежнему работать. Иерархия JSON используется только для генерации ключевого пути, не более того.

Panagiotis Kanavos 11.10.2018 10:24

Спасибо, что указали на это - это был всего лишь пример, и я его изменил.

lonix 11.10.2018 10:28

@Ionix, ответ все тот же. Все - это путь к значениям. Максим объясняет, как это работает. Ваш второй пример переопределяет только MySectionOuter::MySection:1::bar и MySectionOuter::MySection:2::baz, но не другие значения. Использование 1 в названии этого не изменило.

Panagiotis Kanavos 11.10.2018 10:33

@PanagiotisKanavos Я не уверен, что понимаю вас - я хочу переопределить только те значения, которые я указал в производственном файле, а все остальное осталось прежним.

lonix 11.10.2018 10:36

Конфигурация @Ionix .NET Core не зависит от JSON. Он может использовать любое количество поставщиков, включая файлы ini, XML, YAML и базы данных, если поставщики возвращают их в виде отдельных значений с ключевым путем. Этот путь всегда Section1::Subsection1::Whatever::...::SettingName. Независимо от структуры файла, все настройки сводятся к этой форме. Если вы хотите загрузить разные списки данных для каждой среды, вам, вероятно, следует использовать другой механизм.

Panagiotis Kanavos 11.10.2018 10:37

@Ionix, в этом случае вам, вероятно, следует опубликовать код, воспроизводящий проблему. Вы отменяете значения MySectionOuter::MySection:1::bar и MySectionOuter::MySection:2::baz. Все остальные должны оставаться такими же - MySectionOuter::MySection:1::foo должен оставаться "1".

Panagiotis Kanavos 11.10.2018 10:39

@PanagiotisKanavos Хорошо, теперь мы на одной странице. Но ответ Maxims объясняет, почему это не интуитивно, я столкнулся именно с этими проблемами. Придется использовать другой подход. Спасибо.

lonix 11.10.2018 10:45

@PanagiotisKanavos: Я не думаю, что вы имели в виду это таким образом, но ваш комментарий может означать, что порядок конфигурации провайдеры не является детерминированным. На самом деле это так. Провайдеры загружаются в том порядке, в котором они определены. Однако порядок отдельных настроек, загружаемых поставщиком, не всегда может быть одинаковым.

Chris Pratt 11.10.2018 14:55

@ChrisPratt вопрос о массивах настроек. Разные поставщики могут возвращать результаты в разном порядке, таким образом создавая другой путь. Например, поставщик базы данных не сможет решить, как упорядочить результаты, подобные тем, которые опубликованы в вопросе.

Panagiotis Kanavos 11.10.2018 14:58

@PanagiotisKanavos Переопределяя настройки в производственном файле в том же порядке, я получаю желаемый эффект. Вы хотите сказать, что я не могу полагаться на это в будущем?

lonix 11.10.2018 15:14

@Ionix вы можете зависеть от порядка в отношении файловых провайдеров. Если вы добавляете другого провайдера, например базу данных, вам необходимо убедиться, что существует что-то, который можно использовать для восстановления полного ключа. База данных может возвращать результаты в любом порядке. Если же запись в базе данных содержит поле Index, вы можете использовать его для создания того же пути настройки, сгенерированного файлом.

Panagiotis Kanavos 11.10.2018 15:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
32
12
9 495
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Согласно этому сообщению в блоге: https://www.paraesthesia.com/archive/2018/06/20/microsoft-extensions-configuration-deep-dive/

Невозможно удалить элементы конфигурации с помощью поставщика.

You can add configuration at override time, but you can’t remove things. The best you can do is override a value with an empty string.

Вместо этого вам следует вводить в appsettings.config минимально необходимую информацию и заполнять соответствующие настройки в более специализированном файле настроек. Например. appsettings.Development.config или ваш appsettings.Production.config. Или, как предлагается в сообщении в блоге:

Since you can’t remove things, specify as little configuration as possible and behave correctly using defaults in your code when configuration isn’t there.

Вопрос в замена, а не в удалении. Замена работает нормально, пока ключ такой же. В массивах индекс является частью ключа

Panagiotis Kanavos 11.10.2018 10:21

@PanagiotisKanavos Вопрос спрашивает, что после применения appsettings.production.config в массиве должно быть меньше элементов. Поскольку каждый элемент массива имеет свой собственный ключ, они должны быть удаленный из конфигурации. Так что я думаю, что ответ все еще актуален.

Philipp Grathwohl 11.10.2018 10:24

Массив содержит такое же количество элементов. Но это те элементы, у которых меньше свойств. OP предполагал, что массив или сами элементы будут заменены. Наверное, не понимал, что имеют значение только сами настройки, а все остальное - лишь путь к значениям

Panagiotis Kanavos 11.10.2018 10:25

Ты прав! Я оставлю ответ, потому что предложение из сообщения в блоге все еще имеет смысл - и после его применения проблема исчезнет.

Philipp Grathwohl 11.10.2018 10:28

Это исправило это для меня очень хорошо. Я просто оставляю эти настройки массива пустыми в корневом файле. Идеально!

Matthew MacFarland 13.08.2021 00:45
Ответ принят как подходящий

На самом деле массивов там при построении конфигурации нет. Это просто словарь пар ключ-значение. Таким образом, вы получаете строковые ключи, что-то вроде "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, если определите только некоторые поля каждого объекта.

Я бы рекомендовал использовать другие файлы для хранения такой информации. Вы также можете заблокировать отладчик там, где загружена конфигурация, и сами посмотреть, как создаются эти ключи, чтобы получить больше информации.

Другие вопросы по теме