首先,为什么
尝试序列化IConfiguration
这种方式不会按照你想要的方式工作。让我们探究一下原因。
序列化接口
Part您没有获得任何属性的原因是因为泛型类型参数Serialize
is IConfiguration
。换句话说,您正在调用:
JsonSerializer.Serialize<IConfiguration>(updatedCfg)
当 System.Text.Json 使用通用参数进行序列化时,它仅(默认情况下没有任何自定义转换器)序列化该接口的公共属性。在这种情况下IConfiguration
没有公共属性(索引器除外),因此您的输出是空的 json。
使用运行时类型信息
Now, 一般来说为了解决这个问题,你可以使用非通用重载并传递类型。例如,看起来像:
JsonSerializer.Serialize(updatedCfg, updatedCfg.GetType());
或者也可以使用object
作为类型参数:
JsonSerializer.Serialize<object>(updatedCfg);
然后 System.Text.Json 将使用运行时类型信息以确定要序列化哪些属性。
The ConfigurationRoot
现在问题的第二部分是,不幸的是,由于配置系统的设计方式,这仍然无法正常工作。这ConfigurationRoot类(结果Build
)可以聚合许多配置源。数据单独存储在每个提供商内部(甚至外部)。当您从配置中请求一个值时,它会循环遍历每个提供程序以找到匹配项。
所有这些都是为了说明您的具体/运行时类型IConfiguration
对象仍然没有您想要序列化的公共属性。事实上,在这种情况下传递运行时类型就可以了worse而不是模仿接口的行为,因为它将尝试序列化该类型的唯一公共属性(ConfigurationRoot.Providers)。这会给你一个列表序列化提供者,每个输入为IConfigurationProvider并且拥有零公共财产。
一个潜在的解决方案
由于您尝试序列化最终绑定到对象的配置,因此解决方法是重新序列化that对象代替:
var stepExample = new ConfigurableClass(9);
cfg.Bind(stepExample);
var json1 = JsonSerializer.Serialize(stepExample, stepExample.GetType());
// or with the generic version which will work here
var json2 = JsonSerializer.Serialize(stepExample);
替代解决方案 -AsEnumerable
IConfiguration
最终是键值对的集合。我们可以利用AsEnumerable扩展方法来创建List<KeyValuePair<string, string>>
从整个配置中。稍后可以将其反序列化并传递给类似的东西AddInMemoryCollection
你将需要Microsoft.Extensions.Configuration.Abstractions 包(这可能已经被传递引用)和以下内容using
指示:
using Microsoft.Extensions.Configuration;
然后您可以创建所有值的列表(其中键为Section:Key
format)
var configAsList = cfg.AsEnumerable().ToList();
var json = JsonSerializer.Serialize(configAsList);
或者你可以使用ToDictionary
并将其序列化。
var configAsDict = cfg.AsEnumerable().ToDictionary(c => c.Key, c => c.Value);
var json = JsonSerializer.Serialize(configAsDict);
两种格式都可以使用AddInMemoryCollection
因为这只需要一个IEnumerable<KeyValuePair<string, string>>
(这两种类型都是)。但是,如果您想使用,您可能需要字典格式AddJsonFile/Stream
因为我不think它们支持一系列键/值对。
字符串,字符串,除了字符串什么都没有
你似乎有这样的印象IConfiguration
对象正在存储int
s, bool
s等(例如)对应于JSON Element类型。这是不正确的。一个内的所有数据IConfiguration
存储在字符串化形式。基本配置提供程序类都期望一个IDictionary<string, string>
充满了数据。甚至 JSON 配置提供程序执行显式的ToString关于价值观。
The 弦型值被转化为强类型当你打电话时Bind
, Get<>
or GetValue<>
。这些利用了配置binder进而使用注册的TypeConverters
以及众所周知的字符串解析方法。但在幕后一切仍然是一根绳子。这意味着你的 json 文件是否有一个带有值的字符串属性并不重要"True"
或具有值的布尔属性true
。绑定器在映射到 a 时会适当地转换该值boolean
财产。
使用上述字典序列化方法将按预期工作。