如何序列化运行时添加“属性”到Json

2023-12-01

我实现了在运行时向具有特殊 SystemComponent.PropertyDescriptor 的对象添加“属性”的可能性。

由于这些属性只能通过 ComponentModel.TypeDescriptor 访问,而不能通过反射访问,因此这些属性在 WPF 环境中运行良好,但在序列化环境中运行不佳。

这是因为据我所知,所有 JSON 序列化程序都使用类型反射。我分析了Newtonsoft.Json、System.Json、System.Web.Script.JavaScriptSerializer、System.Runtime.Serialization.Json。

我认为我无法使用这些序列化器中的任何一个,因为这些序列化器都不允许修改实例上属性的检索(例如,ContractResolver 是不可能的)。

有没有办法让 JSON 序列化与这些序列化程序之一一起工作?也许通过特殊配置,覆盖序列化器或类似的某些方法? 是否有其他序列化器可以满足此要求?

背景:

运行时属性的想法基于这个博客条目.

序列化要求来自使用 dotNetify,它序列化视图模型以将它们发送到客户端。

目前,我制作了 dotnetify 的一个分支,并通过使用 Newtonsoft.Json 和递归助手进行部分序列化,为序列化制定了临时解决方法。 (如果感兴趣的话可以查看 diff:the Fork).


一种可能性是创建一个custom ContractResolver当序列化特定类型的对象时TTarget,添加合成的ExtensionDataGetter对于指定的目标,返回一个IEnumerable<KeyValuePair<Object, Object>>其对应的属性中指定的DynamicPropertyManager<TTarget>.

首先,定义合约解析器如下:

public class DynamicPropertyContractResolver<TTarget> : DefaultContractResolver
{
    readonly DynamicPropertyManager<TTarget> manager;
    readonly TTarget target;

    public DynamicPropertyContractResolver(DynamicPropertyManager<TTarget> manager, TTarget target)
    {
        if (manager == null)
            throw new ArgumentNullException();
        this.manager = manager;
        this.target = target;
    }

    protected override JsonObjectContract CreateObjectContract(Type objectType)
    {
        var contract = base.CreateObjectContract(objectType);

        if (objectType == typeof(TTarget))
        {
            if (contract.ExtensionDataGetter != null || contract.ExtensionDataSetter != null)
                throw new JsonSerializationException(string.Format("Type {0} already has extension data.", typeof(TTarget)));
            contract.ExtensionDataGetter = (o) =>
                {
                    if (o == (object)target)
                    {
                        return manager.Properties.Select(p => new KeyValuePair<object, object>(p.Name, p.GetValue(o)));
                    }
                    return null;
                };
            contract.ExtensionDataSetter = (o, key, value) =>
                {
                    if (o == (object)target)
                    {
                        var property = manager.Properties.Where(p => string.Equals(p.Name, key, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();
                        if (property != null)
                        {
                            if (value == null || value.GetType() == property.PropertyType)
                                property.SetValue(o, value);
                            else
                            {
                                var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings { ContractResolver = this });
                                property.SetValue(o, JToken.FromObject(value, serializer).ToObject(property.PropertyType, serializer));
                            }
                        }
                    }
                };
            contract.ExtensionDataValueType = typeof(object);
        }

        return contract;
    }
}

然后按如下方式序列化您的对象:

var obj = new object();

//Add prop to instance
int propVal = 0; 
var propManager = new DynamicPropertyManager<object>(obj);
propManager.Properties.Add(
    DynamicPropertyManager<object>.CreateProperty<object, int>(
    "Value", t => propVal, (t, y) => propVal = y, null));

propVal = 3;

var settings = new JsonSerializerSettings
{
    ContractResolver = new DynamicPropertyContractResolver<object>(propManager, obj),
};

//Serialize object here
var json = JsonConvert.SerializeObject(obj, Formatting.Indented, settings);

Console.WriteLine(json);

根据需要输出,

{"Value":3}

显然,这可以扩展到序列化具有动态属性的对象图,方法是将动态属性管理器和目标的集合传递给增强的DynamicPropertyContractResolver<TTarget>。基本思想是创建一个合成的ExtensionDataGetter (and ExtensionDataSetter只要合约解析器有某种机制从正在(反)序列化的目标映射到其目标,就可以工作DynamicPropertyManager.

限制:如果TTarget类型已经有一个扩展数据会员,这行不通。

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

如何序列化运行时添加“属性”到Json 的相关文章

  • 将类对象放置在向量中?

    我注意到我可以将一个类放置在一个向量中 这是我的程序 我收到以下错误 out blackjack exe blackjack obj blackjack obj error LNK2019 unresolved external symbo
  • Environment.CurrentDirectory 与 System.IO.Directory.GetCurrentDirectory

    我正在编写一个 Net WinForms 并不断在调试和发布配置之间切换 并且有一些文件我需要任一配置才能访问 我想做的是将文件放在 BIN 文件夹中的公共目录中 这样它看起来像这样 MyProject Bin CommonFiles My
  • MVC3中设置下拉列表中的所选项目

    我必须为视图中的下拉列表设置所选项目 但它不起作用 View div class editor label Html LabelFor model gt model Gender div div class editor field Htm
  • 未找到 Boost 库,但编译正常

    我正在尝试在 C 中使用 boost 的文件系统 使用时看起来编译没问题 c c Analyse c o Analyse o g W Wall L usr local lib lboost filesystem lboost system
  • 循环遍历 C 结构中的元素以提取单个元素的值和数据类型

    我有一个要求 我有一个 C 语言的大结构 由大约 30 多个不同数据类型的不同元素组成 typedef struct type1 element1 type2 element2 type3 element3 type2 element4 1
  • 有些有助于理解“产量”

    在我不断追求少吸的过程中 我试图理解 产量 的说法 但我不断遇到同样的错误 someMethod 的主体不能是迭代器块 因为 System Collections Generic List 不是迭代器接口类型 这是我被卡住的代码 forea
  • extern 声明和函数定义都在同一文件中

    我只是浏览了一下gcc源文件 在gcc c 我发现了类似的东西 extern int main int char int main int argc char argv 现在我的疑问是extern是告诉编译器特定的函数不在这个文件中 但可以
  • 返回视图作为 JSON 对象的一部分

    我有一个应用程序只加载一次完整视图 我这样做的原因并不重要 重要的是 其余内容只会以部分视图的形式返回 除了一些内容之外 我还有一些 JSON 对象 我想通过每个 AJAX 请求在服务器之间来回传递 有没有办法返回一个 JSON 对象 并将
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • C++中判断unicode字符是全角还是半角

    我正在编写一个终端 控制台 应用程序 该应用程序应该包装任意 unicode 文本 终端通常使用等宽 固定宽度 字体 因此要换行文本 只需计算字符数并观察单词是否适合一行并采取相应的操作 问题是 Unicode 表中的全角字符在终端中占用了
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • Oauth2中如何同时撤销RefreshToken和使AccessToken失效

    我正在使用 Owin Oauth2 授权和资源服务器相同 开发单页面应用程序 AngularJS Net MVC Json Rest API 的身份验证流程 我选择了 Bearer Token 路由而不是传统的 cookie session
  • 模板类的模板构造函数的 C++ 显式模板特化

    我有一个像这样的课程 template
  • WPF DataGrid / ListView 绑定到数组 mvvm

    我们假设你有 N 个整数的数组 表示行数的整数值 在模型中 该整数绑定到视图中的 ComboBox Q1 如何将数组 或数组的各个项目 绑定到 DataGrid 或 ListView 控件 以便 当您更改 ComboBox 值时 只有那么多
  • 了解 Lambda 表达式和委托 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我已经尝试解决这个问题很长一段时间了 阅读在线博客和文章 但到目前为止还没有成功 什么是代表 什么是 Lambda 表达式 两者的优点
  • 在 Win32 控制台应用程序中设置光标位置

    如何在 Win32 控制台应用程序中设置光标位置 最好 我想避免制作句柄并使用 Windows 控制台功能 我花了整个早上沿着那条黑暗的小巷跑 它产生的问题比它解决的问题还要多 我似乎记得当我在大学时使用 stdio 做这件事相对简单 但我
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include

随机推荐

  • Java线程池[关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我想学习用Java写一个线程池 有人能给我指出有用的资源吗 看看 Doug Lea 的书 它们现在已经相当老了 除非他发布了新书 不确定 但是 1 5 中添加的并发包是基于他的线程库
  • 为什么Assembly x86_64系统调用参数不像i386那样按字母顺序排列

    有一个问题困扰着我 那么 为什么在x86 32 the 参数在我认为在的寄存器中传递按字母顺序 eax ecx edx esi and ranked order esi edi ebp syscall arg0 arg1 arg2 arg3
  • Android NDK 链接

    我正在尝试构建一个调用 C 后端的 Android 应用程序 该后端使用 ZeroMQ 进行消息传递 根据安卓构建页面在 ZeroMQ 指南上 我构建了 ndk 版本 6 的本机工具链 并使用它 成功 构建了 ZeroMQ 但是 当我使用
  • 我们如何等待 HTTP 请求完成?

    使用 SO 上的几个答案 我们已经成功编写并执行了一个基本的 HTTP 请求 import Foundation let url URL URL string http jsonplaceholder typicode com posts
  • 连接/从网络驱动器复制

    不完全确定如何解决这个问题 我做了一些研究 但还是不够 尝试连接到工作中的网络驱动器并复制出最新的文件夹 更新到项目 对我来说 目录以 开头 但是当我将其添加到字符串变量时 它不会连接 并且在我时不会显示尝试检查一下 这有一个过程吗 这就是
  • 使用 java 8 中的流反转映射[重复]

    这个问题在这里已经有答案了 我有一个Map
  • 为什么 String.Empty 是无效的默认参数?

    如果我输入以下内容 public Response GetArticles string Filter String Empty Body Visual Studio 给我这个错误 Filter 的默认参数值必须是编译时常量 如果我改变St
  • 读取Excel文件工作表名称

    我有一个导出过程 可将数据从 Access 表传输到 Excel 文件 有几次我遇到了问题 该过程没有在 Excel 中生成一张或多张工作表 1 张工作表 1 个表格 因此 当传输完成后 我希望 Access 检查所有工作表是否都位于 Ex
  • 如何解析具有浏览器兼容性的可编辑 DIV 文本

    我将 div 设为可编辑 当我尝试解析 div 的文本时 我需要执行以下正则表达式 innerDOM div I had downloaded all the material from the Intern br You will fin
  • AngularJS ng-options 选定值的问题

    在 AngularJS 中使用 ng options 时 我遇到了一个奇怪的问题 我的场景非常简单 与 ng model 绑定一个值作为所选选项 从后端加载 选择 的值 将加载的值绑定到 select 我从后端加载的对象是一个键 值 例如
  • Access SQL - 插入多行不起作用

    INSERT INTO EMP 1 EMP NUM EMP LNAME EMP FNAME EMP INITIAL EMP HIREDATE JOB CODE VALUES 101 News John G 08 Nov 00 502 102
  • 如何在 fancybox V2 中为 iframe 设置不同的高度/宽度?

    我一直在使用 Fancybox 1 3 4 就在那里 我在链接本身中有 iframe 的尺寸 这是我如何拥有它的一个例子 test html width 675 height 470 当我单击链接 fancybox 时 将打开具有这些尺寸的
  • 在 Fortran 90 中打开多个文件

    我想打开 10 000 个文件 文件名从abc25000 until abc35000并将一些信息复制到每个文件中 我写的代码如下 PROGRAM puppy IMPLICIT NONE integer i CHARACTER len 3
  • 在 XNA 中沿着曲线路径制作 Sprite 动画

    我想在 XNA 游戏中实现弹道轨迹 并试图找出使弹丸遵循重力曲线的最佳方法 我能想到的最好的办法是首先计算曲线并存储在 Curve 类中 然后让精灵沿着那条曲线移动 但我无法真正弄清楚如何沿着该曲线实际移动精灵 我该怎么做 或者有更好的方法
  • 如何在scrollview中滚动RecyclerView

    如何在scrollview中滚动RecyclerView上方的所有内容 我必须在滚动视图中实现 RecyclerView 如下代码所示 但不能滚动 RecyclerView 请给出答案
  • Delphi - 使用 ListView 拖放

    晚上好 我有这个代码可以使用拖放方法用于files TForm1 class TForm public procedure DropFiles var msg TMessage message WM DROPFILES end proced
  • Azure 事件网格 Blob 存储 - 防止重复 Blob 创建事件?

    我在周五的客户测试期间注意到 Blob 存储事件有一点奇怪的行为 现在我想知道是否存在导致双事件 创建 Blob 的已知情况 因此基本上外部应用程序将 blob 写入容器 大多数 blob 像往常一样只触发一个 blob 创建的事件 但由于
  • 如何在 tkinter 中访问不同类的变量?

    我已经搜索了很多 但我仍然不知道如何访问 python 中不同类的变量 在这种情况下我想访问变量self v from PageOne上课到PageTwo class 这是我的代码 import tkinter as tk import s
  • 如何将查询字符串值从 AWS API Gateway 传递到 Lambda C# 函数

    我有一个 C 方法 已成功将其发布为 AWS Lambda 函数 它看起来像这样 public class MyClass public async Task
  • 如何序列化运行时添加“属性”到Json

    我实现了在运行时向具有特殊 SystemComponent PropertyDescriptor 的对象添加 属性 的可能性 由于这些属性只能通过 ComponentModel TypeDescriptor 访问 而不能通过反射访问 因此这