使用 System.Text.Json 将 IConfiguration 序列化回 Json

2023-11-24

我将一些 IConfiguration 作为 json 存储在我的 sqlserver 数据库中,这样我就可以将它们绑定到一些已经构造的类以提供动态设置。

在某些时候,我可能会在运行时更改新的绑定属性,然后更新数据库。问题是,当我需要时,该类可能有更多不应绑定且不应序列化的属性。因此,我将 IConfiguration 保留为我的类的属性。我使用这种方法的另一个原因是我需要从已加载配置的类中实例化其他子类,并在执行时将它们保存到数据库中。

问题是,当我序列化 IConfiguration 时,我只得到一个空的 json 字符串,如“{}”。 我想我可以利用 .AsEnumerable() 做一些恶作剧,但没有更好的方法吗?

我的示例代码看起来有点像这样

public class ConfigurableClass
{

    public int ChildrenCount { get; set; } = 1069;
    public bool IsFast { get; set; } = false;
    public bool HasChildren { get; set; } = false;

    public int Id { get; }

    public ConfigurableClass(int id) { Id = id; }
}

static void Main(string[] args)
{

    IEnumerable<string> configs = SqlConfigLoader.LoadConfig();

    foreach (var str in configs)
    {
        Console.WriteLine("Parsing new Config:");

        var builder = new ConfigurationBuilder();

        IConfiguration cfg = builder.AddJsonStream(new MemoryStream(Encoding.Default.GetBytes(str)))
                .Build();

        var stepExample = new ConfigurableClass(9);

        cfg.Bind(stepExample);

        //do work with the class that might change the value of binded properties                   

        var updatedCfg = cfg;

        Console.WriteLine(JsonSerializer.Serialize(updatedCfg));

        Console.WriteLine();
    }

    Console.ReadLine();
}

Edit

我还尝试了一种不同的方法,将 IConfiguration 转换为像这样的嵌套字典

ublic static class IConfigurationExtensions
{
   public static Dictionary<string,object> ToNestedDicionary(this IConfiguration configuration)
   {
       var result = new Dictionary<string, object>();
       var children = configuration.GetChildren();
       if (children.Any()) 
           foreach (var child in children)
               result.Add(child.Key, child.ToNestedDicionary());
       else 
           if(configuration is IConfigurationSection section)
               result.Add(section.Key, section.Get(typeof(object)));

       return result;
   }        
}

但我丢失了给定 JsonElement 背后的隐式类型:

如果我序列化生成的字典,我会得到类似“Property”:“True”而不是“Property”:true


首先,为什么

尝试序列化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对象正在存储ints, bools等(例如)对应于JSON Element类型。这是不正确的。一个内的所有数据IConfiguration存储在字符串化形式。基本配置提供程序类都期望一个IDictionary<string, string>充满了数据。甚至 JSON 配置提供程序执行显式的ToString关于价值观。

The 弦型值被转化为强类型当你打电话时Bind, Get<> or GetValue<>。这些利用了配置binder进而使用注册的TypeConverters以及众所周知的字符串解析方法。但在幕后一切仍然是一根绳子。这意味着你的 json 文件是否有一个带有值的字符串属性并不重要"True"或具有值的布尔属性true。绑定器在映射到 a 时会适当地转换该值boolean财产。

使用上述字典序列化方法将按预期工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 System.Text.Json 将 IConfiguration 序列化回 Json 的相关文章

  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 使用 C# 中的 CsvHelper 将不同文化的 csv 解析为十进制

    C 中 CsvHelper 解析小数的问题 我创建了一个从 byte 而不是文件获取 csv 文件的类 并且它工作正常 public static List
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 使用.Net/C# 计算集合的频率分布

    是否有一种快速 简单的方法来使用 Linq 或其他方式计算 Net 集合的频率分布 例如 任意长的 List 包含许多重复项 遍历列表并计算 跟踪重复次数的巧妙方法是什么 查找列表中重复项的最简单方法是将其分组 如下所示 var dups
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • VB.NET 中的静态方法实现

    我很困惑Static在 VB NET 中的实现 在 C 中 我们可以创建静态类和静态方法来为我们的应用程序编写实用方法 现在 VB NET 让我们创建Module代替静态类 如果我们在模块中创建一个方法 默认情况下它会变成静态的 但在我的应
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 如何在当前 Visual Studio 主机内的 Visual Studio 扩展中调试使用 Roslyn 编译的代码?

    我有一个 Visual Studio 扩展 它使用 Roslyn 获取当前打开的解决方案中的项目 编译它并从中运行方法 程序员可以修改该项目 我已从当前 VisualStudioWorkspace 成功编译了 Visual Studio 扩
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐

  • 如何在SpriteKit中创建绳子?

    我想制作一根像图中所示的绳子video 开发这样的绳子的最佳方法是什么 我已经尝试过开始 我认为最好的方法是制作许多小 绳子 部件并用销接头连接它们 这真的是最好的吗 但我不知道如何开始 也许有人可以给我一些示例代码 THX 我是该视频的作
  • 如何将 CMS 添加到现有网站 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我有一个现有的 ASP NET 网站 我想轻松地向其添加 CMS 功能 该网站是房地产经纪人的房地产网站 由数据库等支持 但是有些页面如 关于我们
  • 如何增加Docker容器默认大小?

    我们创建了默认大小为 10GB 的 docker 镜像 并且已经加载了 cassandra 数据 现在数据已满 意味着没有空间 谁能告诉我如何在不丢失现有数据的情况下将 docker 容器大小从 10GB 增加到 40GB 使用 devic
  • UniVerse学习材料[关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我最近接触到了 UniVerse 的专有后代 有谁知道我在哪里可以获得好的教程或温习其更受欢迎的父级的语法怪癖 我什至不知道如何获得表格列表 导航很困难 而且我没有看到任何手册页 更
  • Drupal localhost 重定向到 www.localhost.com

    我正在开发一个 drupal 站点 我将其签出 svn 到我的本地主机 现在的问题是 当我去 http www site com 一切正常 但是当我去 http localhost 工作 站点 我被重定向到 http www localho
  • 无法使用 R 中的 sqlSave 附加到 SQL Server 表

    我正在尝试使用 R 中 RODBC 包的 sqlSave 函数更新 SQL 表 数据存在于数据框中 当我尝试运行命令时 sqlSave DBConn dat df verbose T tablename table append T 我收到
  • 如何增加 ASP.NET WebAPI Post 调用的 json 大小限制?

    我在页面上的表单有点太大了 它收集每月的测量数据 请看一下示例 Year 2013 Month 3 Records Id 0 Date 3 1 2013 RiverSection 5 UserNumber 56 Id 0 Date 3 1
  • 如何在 Swift 3 中将 __NSMallocBlock__ 转换为其基础类型?

    I had a trick帮助测试UIAlertController在 Swift 2 x 中有效 extension UIAlertController typealias AlertHandler convention block UI
  • 无法编译任何C++程序;错误:未知类型名称“uint8_t”

    编辑2 问题是不是简单的印刷错误 我在下面的日志中犯了一个拼写错误 我已更正该错误 但问题仍然存在 编辑 在尝试下面之后 我错误地使用 gcc 而不是 g 运行了一次 g 以前就存在这个问题 现在也存在 我目前使用的是 MacOS High
  • 如何从从另一个文件夹中加载的程序集中获取类型?

    我使用以下代码 Assembly LoadFile the assembly in another folder var type Type GetType the full name of the type 即使程序集已经在这行代码之前加
  • 如何使用 sed 替换源文件中的版权/许可证标头?

    我需要用 Apache License 2 0 标头替换所有 Java 源文件中的 LGPL 许可证标头 即 Copyright c 2012 Tyler Treat This file is part of Project Foo Pro
  • 直接P2P连接

    这个主题类似于这个线程 我对网络编程主题相当陌生 除了在单个本地计算机上执行基本的 TCP UDP 之外 从未做过任何其他事情 现在我正在开发一个需要 P2P 网络支持的应用程序 更具体地说 我需要应用程序通过互联网进行连接和通信 最好不使
  • 如何使用 Apache POI (Java) 在 Excel 中创建表单控件(单选、复选框、按钮等)?

    我是否可以使用 Java 通过 Apache POI 库为 Excel 生成表单控件 如果这不可能 还有什么替代方案 我真的需要这个来完成我的工作 预先感谢 对于 Excel 2007 或更高版本 由于 Apache POI 在 OpenX
  • 在后台运行 JavaExec 任务,然后在构建完成时终止

    我试图找出如何启动一个 JavaExec 任务来生成 Jetty 服务器而不阻塞后续任务 另外 我需要在构建完成后终止该服务器 知道我该怎么做吗 我知道该线程是 2011 年的 但我仍然偶然发现了这个问题 这是使用 Gradle 2 14
  • 为 SSL 配置 SSRS

    我有一个运行 SSRS 2014 的 SSRS 实例 我想将其配置为通过 SSL 使用 服务器位于http reports mydomain2 com 我从 GoDaddy 购买了域名 www mydomain com 上的多 SSL 证书
  • 使用流填充多维数组

    我是 Java 8 的新手 目前无法完全掌握 Streams 是否可以使用 Stream 函数操作来填充数组 这是我如何使用标准 for 循环执行此操作的示例代码 public static void testForLoop String
  • 这种锁定和管理锁定异常的解决方案有什么问题?

    我的目标是在应用程序中实现线程安全功能和异常处理的约定 我对线程管理 多线程的概念相对较新 我在用 NET 3 5 阅读本文后 我编写了以下辅助方法来包装所有锁定的操作http blogs msdn com b ericlippert ar
  • 获取尚未应用的类的 CSS 属性值

    在 jQuery 中 我可以使用以下方法获取选择器的 CSS 属性值css方法并传递属性名称 例如 myElement css backgroundImage 我的问题是 如何从一个类中获取 css 属性值not尚未应用于any元素 如同
  • 如何找回我的 MySQL 用户名和密码?

    我丢失了 MySQL 用户名和密码 我该如何取回它 停止 MySQL 进程 使用 skip grant tables 选项启动 MySQL 进程 使用 u root 选项启动 MySQL 控制台客户端 列出所有用户 SELECT FROM
  • 使用 System.Text.Json 将 IConfiguration 序列化回 Json

    我将一些 IConfiguration 作为 json 存储在我的 sqlserver 数据库中 这样我就可以将它们绑定到一些已经构造的类以提供动态设置 在某些时候 我可能会在运行时更改新的绑定属性 然后更新数据库 问题是 当我需要时 该类