Загрузка конфигурации запуска из JSON, находящегося в памяти

Я изучаю, как загрузить конфигурацию запуска в .NET Core. Я заметил, что есть разные способы сделать это, я видел XML, JSON, файл инициализации и словарь, расположенный в памяти (я вернусь к этому позже). Я использую что-то вроде кода ниже:

new ConfigurationBuilder().AddJsonFile("file.json").Build();

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

О словаре, расположенном в памяти. Его легко построить вручную, но как насчет сложных и слишком иерархических структур JSON? Насколько я знаю, словарь

словарь ‹строка, строка›

ключом которого являются родительские элементы дерева, объединенные посредством: одновременного управления повторяющимися узлами, их перечисления и т. д. Создание этого алгоритма с нуля затруднительно.


person mra    schedule 28.06.2017    source источник
comment
Вы также можете читать JSON из строки. Проверьте эту ссылку stackoverflow.com/a/29843542/2298362   -  person Prabodh M    schedule 28.06.2017
comment
@PrabodhM Спасибо за ваш комментарий, но он не имеет отношения к моему вопросу. Я спрашиваю: есть ли способ загрузить ConfigurationBuilder () из json в память?   -  person mra    schedule 28.06.2017
comment
Извините, я неправильно истолковал ваш вопрос.   -  person Prabodh M    schedule 28.06.2017


Ответы (4)


Используйте пакет NuGet Microsoft.Extensions.Configuration.Json ›= 3.0.0

var json = "{ \"option1\": 1, \"option2\": \"abc\", }";
var configuration = new ConfigurationBuilder().AddJsonStream(new MemoryStream(Encoding.ASCII.GetBytes(json))).Build();
person FatTiger    schedule 29.02.2020
comment
Возможно, это решение не было доступно, когда был задан исходный вопрос, но, безусловно, кажется самым простым способом создать конфигурацию непосредственно из строки JSON. Идеально подходит для модульного тестирования! - person Ben Wesson; 12.03.2020
comment
Остерегайтесь проблем с использованием AddJsonStream при запуске нескольких .Build (). Просто столкнулся с этой проблемой, потому что первый .Build () в IConfigurationBuilder уничтожит начальные потоки. Отчет об ошибке здесь: github.com/dotnet/extensions/issues/3645 - person Matt; 21.10.2020

Мне очень понравился ответ Адама, но реализации интерфейса, с которыми он связался, были немного монолитными. Вот один поменьше:

public class InMemoryFileProvider : IFileProvider
{
    private class InMemoryFile : IFileInfo
    {
        private readonly byte[] _data;
        public InMemoryFile(string json) => _data = Encoding.UTF8.GetBytes(json);
        public Stream CreateReadStream() => new MemoryStream(_data);
        public bool Exists { get; } = true;
        public long Length => _data.Length;
        public string PhysicalPath { get; } = string.Empty;
        public string Name { get; } = string.Empty;
        public DateTimeOffset LastModified { get; } = DateTimeOffset.UtcNow;
        public bool IsDirectory { get; } = false;
    }

    private readonly IFileInfo _fileInfo;
    public InMemoryFileProvider(string json) => _fileInfo = new InMemoryFile(json);
    public IFileInfo GetFileInfo(string _) => _fileInfo;
    public IDirectoryContents GetDirectoryContents(string _) => null;
    public IChangeToken Watch(string _) => NullChangeToken.Singleton;
}

Затем, согласно ответу Адама, вы можете использовать:

var memoryFileProvider = new InMemoryFileProvider(jsonString);
var configuration = new ConfigurationBuilder()
    .AddJsonFile(memoryFileProvider, "appsettings.json", false, false)
    .Build();
person Rob Lyndon    schedule 19.09.2018

В ASPNETCORE 2.0 (не уверен в других версиях) вы можете использовать config.AddInMemoryCollection:

var host = new WebHostBuilder()
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        config.AddInMemoryCollection(new Dictionary<string, string>()
        {
            { "MyParentKey:MySubKey", "MyValue" }
        });
    });

ОБНОВЛЕНИЕ: я адаптировал код из приведенной ниже ссылки, чтобы проанализировать строку JSON и вернуть словарь:

ИСПОЛЬЗОВАНИЕ:

var dictionary = JsonConfigurationParser.Parse(MyJsonString);
person Lee Gunn    schedule 17.01.2018
comment
Ответ помогает, но все же не является полным. Как бы вы смоделировали сложный объект json, это было бы утомительно, как словарь. Мы ищем способ напрямую загрузить строку JSON. - person JohnKoz; 11.08.2018
comment
@JohnKoz - В Github есть код MS, который уже преобразует JSON в правильный формат словаря (это внутренний класс). Я адаптировал его и добавил к ответу. Надеюсь, это поможет. - person Lee Gunn; 11.08.2018
comment
Спасибо, ваш первоначальный ответ очень приятный. Очень хорошо работает для модульного тестирования на dotnetcore 2 - person Jeremy Ray Brown; 14.10.2020

Вы можете относительно легко повторно использовать существующий API (Microsoft.Extensions.Configuration.Json), реализовав поставщик файлов в памяти.

Вам понадобиться

  • фиктивная реализация IFileProvider - что-то вроде того, что использовалось здесь.
  • фиктивная реализация IFileInfo - вы можете позаимствовать одну отсюда.

В приведенном ниже коде показано, как все это собрать:

var json = "{ \"option1\": 1, \"option2\": \"abc\", }";
var memoryJsonFile = new MemoryFileInfo("config.json", Encoding.UTF8.GetBytes(json), DateTimeOffset.Now);
var memoryFileProvider = new MockFileProvider(memoryJsonFile);

var configuration = new ConfigurationBuilder()
    .AddJsonFile(memoryFileProvider, "config.json", false, false)
    .Build();

Console.WriteLine(configuration["option2"]);

И вот, пожалуйста;)

person Adam Simon    schedule 11.08.2018