Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
3 / 3 / 1
Регистрация: 21.04.2023
Сообщений: 14
.NET 9

Конфигурация json с параметрами вместе с DI .NET

11.06.2025, 08:37. Показов 1515. Ответов 10

Студворк — интернет-сервис помощи студентам
У меня возникла проблема при конфигурировании приложения с использованием внедрения зависимостей и IOptions<T>. У программы есть конфиг с пользовательскими настройками. Для редактирования настроек пользователь может использовать саму программу, но я допускаю, что любознательный пользователь может хотеть открыть сам файл конфигурации. Для этого я стараюсь поддерживать его в красивом виде. Чтобы это сделать, нужно использовать некоторые опции и атрибуты. К примеру, сериализация перечислений в виде именований, а не значений. Для этого требуется использовать JsonStringEnumConverter, но поставщик конфигурации json видимо это делает за меня. Было бы всё отлично, но с .NET 9 пришла возможность задавать иные имена полям перечисления для сериализации. Для этого был добавлен JsonStringEnumMemberNameAttribute, который поставщик конфигураций json видимо не использует и из-за чего я не могу сделать конфиги еще краше. Мне кажется, что для решения проблемы нужно писать свой поставщик. Может быть я что-то упускаю и у кого-то есть более элегантное решение?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.06.2025, 08:37
Ответы с готовыми решениями:

Конфигурация приложения .NET. XML конфигурация
Здравствуйте. Третьи сутки колдую над конфигурацией приложения, написанного на шарпе. Перелопатил...

Как правильно прописать коллекцию в JSON конфигурации appsettings.json?
Всем привет. Подскажите, как в appsettings.json правильно прописать список админов? Я здесь...

Ошибка при обработке Json - Cannot deserialize the current JSON array because the type requires a JSON object
Всем привет! Помогите, плиз, разобраться с ошибкой: An unhandled exception of type...

10
 Аватар для Andrey-MSK
3308 / 2196 / 386
Регистрация: 14.08.2018
Сообщений: 7,390
Записей в блоге: 4
11.06.2025, 08:52
Цитата Сообщение от KebabGGbab Посмотреть сообщение
что любознательный пользователь может хотеть открыть сам файл конфигурации
Спрятать его куда-нибудь подальше? В каталоге пользователя (AppData) есть куча мест куда его можно положить
Можно использовать не файл в редактируемом формате, а файл локальной СУБД, к примеру SQLite, в него точно просто так не залезешь...
1
3 / 3 / 1
Регистрация: 21.04.2023
Сообщений: 14
11.06.2025, 09:07  [ТС]
Это был бы подходящий вариант, но я идеалист и стремлюсь к совершенству, я сам бы хотел, чтобы конфиг был красивый, даже если его никогда не откроет ни один пользователь. В данном случае моя идеальность подорвана и я вынужден поинтересоваться о существующих вариантах решения проблемы.
Как я указал в тексте вопроса, мне кажется, что можно написать собственный поставщик. Правильно ли это?

Вообще, конфигурации храню в AppData, куда вряд ли залезет пользователь, но хотелось бы совершенства.
0
 Аватар для qwerty.123
19 / 18 / 1
Регистрация: 25.05.2025
Сообщений: 39
11.06.2025, 20:39
Цитата Сообщение от KebabGGbab
Как я указал в тексте вопроса, мне кажется, что можно написать собственный поставщик
Мне в прошлом пришлось писать NuGet-пакеты (абстракцию и реализацию), отвечающие за шифрование/расшифровку секретной информации в любом текстовом файле. В частности, нас интересовал JSON, потому что мы не нашли для .NET 7 и .NET 8 коробочного бесплатного способа шифрования секций в конфигах JSON наподобие тому, как это имеется для конфигурационных файлов XML. Для случаев, когда приложение использует JSON конфиги, Майкрософт везде рекомендует использовать платные решения, вроде Vault для хранения секретов, тем самым вынося их из конфигов.

Поэтому мне пришлось самому написать пакеты, которые анализирует любой текст, находят в нём блоки секретов и в рантайме выполняют затребованную операцию: шифруют, расшифровывают или распаковывают все найденные секреты. Всё это делается через сертификаты хранилища уровня Local Machine или Curent User (смотря что указано в настройках конкретного секрета). Сейчас используем эти пакеты во всех наших проектах.

А по поводу организации конфигов... Обычно я разношу разные настройки по разным конфигурационным JSON-файлам, сохраняемым в подкаталоге .\Configurations. В рантайме, при построении IConfigurationRoot, загружаю те конфиги, которые либо являются общими для любого окружения, либо соответствуют целевому окружению. В процессе загрузки, через написанный мною метод расширения, выполняю расшифровку всех зашифрованных значений. А при считывании инфы из конфигов всегда делаю биндинги на соответствующие классы.

Набор конфигурационных файлов может выглядеть по разному, например:

serilog.json
serilog.Development.json
serilog.Staging.json
serilog.Production.json

crm.json
crm.Development.json
crm.Staging.json
crm.Production.json

messageBrokers.json
messageBrokers.Development.json
messageBrokers.Staging.json
messageBrokers.Production.json

и т.п.
Мне так удобней, чем когда имеется один общий огромный конфиг-файл (или один общий и по дополнительному на каждое окружение).

Саму конфигурацию в DI (Майкрософта или Autofac) я регистрирую просто как синглтон интерфейсов IConfigurationRoot и IConfiguration.

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

А по поводу енумов... Я предпочитаю, чтобы они в конфигах записывались как реальные имена енум-значений, используемых в коде, без трансформации во что-то более читабельное (меня это будет только сбивать с толку, т.к. придётся постоянно держать в голове: мол записано так, а на самом деле это означает нечто иное, особенно если значения близки по смыслу).
1
Эксперт .NET
 Аватар для Wolfdp
3782 / 1756 / 371
Регистрация: 15.06.2012
Сообщений: 6,516
Записей в блоге: 3
11.06.2025, 21:24
Цитата Сообщение от KebabGGbab Посмотреть сообщение
Мне кажется, что для решения проблемы нужно писать свой поставщик.
Я бы порыл документацию на предмет возможности сконфигурировать сериализатор, который вызывается для чтения опций. С большой вероятностью там это должно быть.
1
 Аватар для Calabonga
14 / 13 / 1
Регистрация: 13.02.2025
Сообщений: 32
12.06.2025, 03:21
Как я указал в тексте вопроса, мне кажется, что можно написать собственный поставщик. Правильно ли это?
Рано или поздно такие вопросы возникают у каждого разработчика. Судя по ответам в топике, это очевидно. Но в моем случае, было не так, я сначала решил хранить настройки ASP.NET MVC приложения в JSON, а не в WebConfig, и даже сделал свой собственный nuget-пакет (посмотреть можно тут), а потом уже появился ASP.NET Core, где вся конфигурация была реализована при помощи паттерна IOptions. Но моя реализация умела "сохранять" настройки, а не только "читать". Я и сейчас часто использую ее, причем не только на ASP.NET Core. Кстати, код открыт и, возможно, поможет вам начать свой пакет.

Кстати, подобных самописных решений у меня много, но в суть в том, что все они работают в комплексе. То есть, начиная новый проект, мне достаточно поставить нужные пакеты и полдела уже готово. Призываю вас создавать для себя комплексные решения — это реально помогает.

Так вот к чему я это всё. А к тому, что если вам действительно не хватает существующей реализации, и вы понимаете, что ваша сборка будет вам реально помогать, то ответ "да, почему бы и нет"...
1
Эксперт .NET
 Аватар для Usaga
14073 / 9290 / 1347
Регистрация: 21.01.2016
Сообщений: 34,877
12.06.2025, 03:36
Цитата Сообщение от KebabGGbab Посмотреть сообщение
Мне кажется, что для решения проблемы нужно писать свой поставщик.
Лично я тут не вижу никакой проблемы. Если пользователь руками полез в конфиг, то красота ему там не нужна. А те, кто без красот теряется, в конфиг не лезут.

Ты точно решаешь реальную проблему?
1
3 / 3 / 1
Регистрация: 21.04.2023
Сообщений: 14
12.06.2025, 05:42  [ТС]
Проблема на самом деле и не совсем в пользователях, на самом деле, как я уже указывал выше, мне просто самому нравится, когда у меня чистый, красивый, опрятный конфиг.
Но я уже написал провайдер, спасибо за советы.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
12.06.2025, 19:11
Цитата Сообщение от KebabGGbab Посмотреть сообщение
К примеру, сериализация перечислений в виде именований, а не значений. Для этого требуется использовать JsonStringEnumConverter, но поставщик конфигурации json видимо это делает за меня. Было бы всё отлично, но с .NET 9 пришла возможность задавать иные имена полям перечисления для сериализации. Для этого был добавлен JsonStringEnumMemberNameAttribute, который поставщик конфигураций json видимо не использует
Конфиги считываются из разных мест: из файлов настроек (json, xml, ini и т.д.), переменных окружения, аргументов командной строки и пр.
Один и тот же объект конфига может быть разбит на части и считываться кусками из разных мест в разных форматах.
Через это поставщики не занимаются десериализацией настроек в объекты конфига, они только предоставляют словарь строк ключ/значение, потому на стадии считывания файла конфига поставщик понятия не имеет какой на выходе должен быть тип. Следовательно, конвертеры не используются.

Десериализацией этих словарей в объекты уже занимется ConfigurationBinder, который понятия не имеет о формате хранилища откуда они были получены: он работает с ключами вида "Logging:LogLevel:Default" и значениями типа "Information", и использует обычную рефлексию, плюс где может — конвертеры типов (TypeConverter), которые применяет только для конвертации значений терминальных узлов ключа.
В примере выше — только для конвертации значения "Information" для свойства Default. Корневой узел и LogLevel создаст через обычный конструктор типа для соответствующего свойства (с небольшими исключениями для коллекций).

Если нужна кастомная десериализация, то для указанного типа надо писать свой TypeConverter из строки там уже прописывать нужную логику.

В репозитории открыта тема для расширения возможностей настроек этого байндера, но пока как-то вяло: https://github.com/dotnet/runtime/issues/83599
2
Эксперт .NET
 Аватар для Wolfdp
3782 / 1756 / 371
Регистрация: 15.06.2012
Сообщений: 6,516
Записей в блоге: 3
13.06.2025, 07:51
Лол, таки "просто указать правила сериализации" не прокатит. Занятно, хотя с точки зрения абстракций наверное это даже хорошо. Всё же JsonStringEnumConverter находится в совершенно другой сборке, нежели Microsoft.Extensions.Configuration.

Цитата Сообщение от kolorotur Посмотреть сообщение
поставщики не занимаются десериализацией настроек в объекты конфига, они только предоставляют словарь строк ключ/значение
Цитата Сообщение от kolorotur Посмотреть сообщение
Следовательно, конвертеры не используются.
Чуть поправлю уточню: конвертор используется на этапе считывания в словарь вида IDictionary<string, string?>, а дальше ноль понимания в какую модель потом эти данные будут пихаться. Если глянуть интерфейс IConfigurationProvider, там тоже ноль завязок на тип данных, только строки.

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

------------------------------

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

Вовзращаясь к вопоросу ТСа -- написать свой поставщик отличное решение. Хотя лично я бы просто в лоб делал Read - Deserialize - Registration и забил.
2
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
13.06.2025, 11:18
Цитата Сообщение от Wolfdp Посмотреть сообщение
конвертор используется на этапе считывания в словарь
Ну да, я имел в виду конвертеры для конечной модели, ака всякие JsonPropertyName-атрибуты.
Конвертация на этапе считывания там вида "как представить иерархию json в виде секция:секция:свойство" и "как int из json перевести в строку". А то что это значение в конце должно быть enum — тут уже, как вы подметили, понимания ноль.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.06.2025, 11:18
Помогаю со студенческими работами здесь

Ошибка при обработке Json - Cannot deserialize the current JSON array because the type requires a JSON object
Дополнительные сведения: Cannot deserialize the current JSON object (e.g. {&quot;name&quot;:&quot;value&quot;}) into...

Разница между ASP.NET Core 2, ASP.NET Core MVC, ASP.NET MVC 5 и ASP.NET WEBAPI 2
Здравствуйте. Я в бекенд разработке полный ноль. В чем разница между вышеперечисленными...

Распарсить с помощью Json.Net приходящий ответ в виде JSON
Нужна помощь с json {&quot;success&quot;:true, &quot;rgInventory&quot;:{ &quot;1025429056&quot;:{...

Json.NET не нравится json - Unexpected character encountered while parsing value
Ошибка при десерилизации такого вот текста: { &quot;ishavework&quot;: false, &quot;num&quot;: null, ...

Десериализация JSON из ВК без JSON.NET
JSON: { &quot;response&quot; : } Мой код: string json = тут текст из спойлера вначале;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru