mra*_*mra 12 .net configuration json build core
我正在研究如何在.Net Core中加载启动配置.我注意到有不同的方法可以做到这一点,我已经看到了XML,JSON,init文件,以及位于内存中的Dictionary(稍后我会回到这里).我正在使用类似下面的代码:
new ConfigurationBuilder().AddJsonFile("file.json").Build();
Run Code Online (Sandbox Code Playgroud)
所有这些都没关系,但是,有没有办法从JSON字符串加载该配置?我的意思是,我不想将json存储在临时文件中,因为它是一个实时构建的文件,它没有任何意义.
关于位于记忆中的字典.它很容易手动构建,但是,复杂和过于分层的JSON结构呢?据我所知,字典是
字典<string,string>
其关键是树的父母连接":"同时管理重复的节点,枚举它们等.痛苦从头开始构建这个算法.
小智 18
使用 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();
Run Code Online (Sandbox Code Playgroud)
我很喜欢Adam的答案,但是他链接到的界面实现有点单一.这是一个较小的一个:
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;
}
Run Code Online (Sandbox Code Playgroud)
然后,按照Adam的回答,您可以使用:
var memoryFileProvider = new InMemoryFileProvider(jsonString);
var configuration = new ConfigurationBuilder()
.AddJsonFile(memoryFileProvider, "appsettings.json", false, false)
.Build();
Run Code Online (Sandbox Code Playgroud)
在 ASPNETCORE 2.0(不确定其他版本)中,您可以使用config.AddInMemoryCollection:
var host = new WebHostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddInMemoryCollection(new Dictionary<string, string>()
{
{ "MyParentKey:MySubKey", "MyValue" }
});
});
Run Code Online (Sandbox Code Playgroud)
更新:我从下面的链接中修改了一些代码来解析一个 JSON 字符串并返回一个字典:
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
namespace Config
{
public class JsonConfigurationParser
{
private JsonConfigurationParser() { }
private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private readonly Stack<string> _context = new Stack<string>();
private string _currentPath;
public static IDictionary<string, string> Parse(string json) => new JsonConfigurationParser().ParseJson(json);
private IDictionary<string, string> ParseJson(string json)
{
_data.Clear();
var jsonConfig = JObject.Parse(json);
VisitJObject(jsonConfig);
return _data;
}
private void VisitJObject(JObject jObject)
{
foreach (var property in jObject.Properties())
{
EnterContext(property.Name);
VisitProperty(property);
ExitContext();
}
}
private void VisitProperty(JProperty property)
{
VisitToken(property.Value);
}
private void VisitToken(JToken token)
{
switch (token.Type)
{
case JTokenType.Object:
VisitJObject(token.Value<JObject>());
break;
case JTokenType.Array:
VisitArray(token.Value<JArray>());
break;
case JTokenType.Integer:
case JTokenType.Float:
case JTokenType.String:
case JTokenType.Boolean:
case JTokenType.Bytes:
case JTokenType.Raw:
case JTokenType.Null:
VisitPrimitive(token.Value<JValue>());
break;
default:
throw new FormatException("Unsupported JSON token");
}
}
private void VisitArray(JArray array)
{
for (int index = 0; index < array.Count; index++)
{
EnterContext(index.ToString());
VisitToken(array[index]);
ExitContext();
}
}
private void VisitPrimitive(JValue data)
{
var key = _currentPath;
if (_data.ContainsKey(key))
{
throw new FormatException("Duplicate Key");
}
_data[key] = data.ToString(CultureInfo.InvariantCulture);
}
private void EnterContext(string context)
{
_context.Push(context);
_currentPath = ConfigurationPath.Combine(_context.Reverse());
}
private void ExitContext()
{
_context.Pop();
_currentPath = ConfigurationPath.Combine(_context.Reverse());
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var dictionary = JsonConfigurationParser.Parse(MyJsonString);
Run Code Online (Sandbox Code Playgroud)
通过实现内存文件提供程序,您可以相对轻松地重用现有 API (Microsoft.Extensions.Configuration.Json)。
你需要
下面的代码演示了如何组装所有这些:
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"]);
Run Code Online (Sandbox Code Playgroud)
你去吧;)