如何通过比较两个 C# 对象来创建 JsonPatchDocument?

2024-02-20

鉴于我有两个相同类型的 C# 对象,我想比较它们以创建 JsonPatchDocument。

我有一个 StyleDetail 类定义如下:

public class StyleDetail
    {
        public string Id { get; set; }
        public string Code { get; set; }
        public string Name { get; set; }
        public decimal OriginalPrice { get; set; }
        public decimal Price { get; set; }
        public string Notes { get; set; }
        public string ImageUrl { get; set; }
        public bool Wishlist { get; set; }
        public List<string> Attributes { get; set; }
        public ColourList Colours { get; set; }
        public SizeList Sizes { get; set; }
        public ResultPage<Style> Related { get; set; }
        public ResultPage<Style> Similar { get; set; }
        public List<Promotion> Promotions { get; set; }
        public int StoreStock { get; set; }
        public StyleDetail()
        {
            Attributes = new List<string>();
            Colours = new ColourList();
            Sizes = new SizeList();
            Promotions = new List<Promotion>();
        }
    }

如果我有两个 StyleDetail 对象

StyleDetail styleNew = db.GetStyle(123);
StyleDetail styleOld = db.GetStyle(456);

我现在想要创建一个 JsonPatchDocument,以便我可以将差异发送到我的 REST API...如何做到这一点?

JsonPatchDocument patch = new JsonPatchDocument();
// Now I want to populate patch with the differences between styleNew and styleOld - how?

在javascript中,有一个库可以做到这一点https://www.npmjs.com/package/rfc6902 https://www.npmjs.com/package/rfc6902

计算两个对象之间的差异:

rfc6902.createPatch({第一个:'克里斯'},{第一个:'克里斯',最后一个: '棕色的'});

[ { op: 'add', path: '/last', value: 'Brown' } ]

但我正在寻找 c# 实现


让我们滥用您的类可序列化为 JSON 的事实! 这是补丁创建者的第一次尝试,它不关心您的实际对象,只关心该对象的 JSON 表示形式。

public static JsonPatchDocument CreatePatch(object originalObject, object modifiedObject)
{
    var original = JObject.FromObject(originalObject);
    var modified = JObject.FromObject(modifiedObject);

    var patch = new JsonPatchDocument();
    FillPatchForObject(original, modified, patch, "/");

    return patch;
}

static void FillPatchForObject(JObject orig, JObject mod, JsonPatchDocument patch, string path)
{
    var origNames = orig.Properties().Select(x => x.Name).ToArray();
    var modNames = mod.Properties().Select(x => x.Name).ToArray();

    // Names removed in modified
    foreach (var k in origNames.Except(modNames))
    {
        var prop = orig.Property(k);
        patch.Remove(path + prop.Name);
    }

    // Names added in modified
    foreach (var k in modNames.Except(origNames))
    {
        var prop = mod.Property(k);
        patch.Add(path + prop.Name, prop.Value);
    }

    // Present in both
    foreach (var k in origNames.Intersect(modNames))
    {
        var origProp = orig.Property(k);
        var modProp = mod.Property(k);

        if (origProp.Value.Type != modProp.Value.Type)
        {
            patch.Replace(path + modProp.Name, modProp.Value);
        }
        else if (!string.Equals(
                        origProp.Value.ToString(Newtonsoft.Json.Formatting.None),
                        modProp.Value.ToString(Newtonsoft.Json.Formatting.None)))
        {
            if (origProp.Value.Type == JTokenType.Object)
            {
                // Recurse into objects
                FillPatchForObject(origProp.Value as JObject, modProp.Value as JObject, patch, path + modProp.Name +"/");
            }
            else
            {
                // Replace values directly
                patch.Replace(path + modProp.Name, modProp.Value);
            }
        }       
    }
}

Usage:

var patch = CreatePatch(
    new { Unchanged = new[] { 1, 2, 3, 4, 5 }, Changed = "1", Removed = "1" },
    new { Unchanged = new[] { 1, 2, 3, 4, 5 }, Changed = "2", Added = new { x = "1" } });

// Result of JsonConvert.SerializeObject(patch)
[
  {
    "path": "/Removed",
    "op": "remove"
  },
  {
    "value": {
      "x": "1"
    },
    "path": "/Added",
    "op": "add"
  },
  {
    "value": "2",
    "path": "/Changed",
    "op": "replace"
  }
]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过比较两个 C# 对象来创建 JsonPatchDocument? 的相关文章

  • 通过增加索引之和来生成排序组合的有效方法

    对于启发式算法 我需要一个接一个地评估特定集合的组合 直到达到停止标准 由于它们很多 目前我正在使用以下内存高效迭代器块生成它们 受到 python 的启发 itertools combinations http docs python o
  • 如何使用 zlib 制作 .zip 文件

    我正在阅读zlib的文档 它相当详细 但我读到了这一行 输出数据将位于zlib格式 与 gzip 或zip formats http www zlib net zlib how html http www zlib net zlib how
  • 在 C# 中生成 HMAC-SHA1

    我正在尝试使用 C 来使用 REST API API 创建者提供了以下用于 hmac 创建的伪代码 var key1 sha1 body var key2 key1 SECRET KEY var key3 sha1 key2 var sig
  • C# 正则表达式用于查找 中具有特定结尾的链接

    我需要一个正则表达式模式来查找字符串 带有 HTML 代码 中的链接 以获取文件结尾如 gif 或 png 的链接 示例字符串 a href site com folder picture png target blank picture
  • 在 C# Winforms 应用程序中嵌入 Windows XP 主题

    我有一个旧版 C Windows 窗体应用程序 其布局是根据 Windows XP 默认主题设计的 由于需要将其作为 Citrix 应用程序进行分发 该应用程序现在看起来像经典主题应用程序 因为 Citrix 不鼓励使用主题系统服务 所以
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 如何将带有自定义分配器的 std::vector 传递给需要带有 std::allocator 的函数?

    我正在使用外部库 pcl 因此我需要一个不会更改现有函数原型的解决方案 我正在使用的一个函数生成一个std vector
  • 2D morton 码编码/解码 64 位

    如何将给定 x y 的莫顿代码 z 顺序 编码 解码为 32 位无符号整数 生成 64 位莫顿代码 反之亦然 我确实有 xy2d 和 d2xy 但仅适用于 16 位宽的坐标 产生 32 位莫顿数 在网上查了很多 但没有找到 请帮忙 如果您可
  • libxml2 xmlChar * 到 std::wstring

    libxml2似乎将所有字符串存储在 UTF 8 中 如xmlChar xmlChar This is a basic byte in an UTF 8 encoded string It s unsigned allowing to pi
  • 默认析构函数做了多少事情

    C 类中的默认析构函数是否会自动删除代码中未显式分配的成员 例如 class C public C int arr 100 int main void C myC new C delete myC return 0 删除 myC 会自动释放
  • 二叉树中的 BFS

    我正在尝试编写二叉树中广度优先搜索的代码 我已将所有数据存储在队列中 但我不知道如何访问所有节点并消耗它们的所有子节点 这是我的 C 代码 void breadthFirstSearch btree bt queue q if bt NUL
  • .NET 客户端中 Google 表格中的条件格式请求

    我知道如何在 Google Sheets API 中对值和其他格式进行批量电子表格更新请求 但条件格式似乎有所不同 我已正确设置请求 AddConditionalFormatRuleRequest formatRequest new Add
  • 为什么要在 C++ 中使用 typedef?

    可以说我有 set
  • WPF。如何从另一个窗口隐藏/显示主窗口

    我有两个窗口 MainWindow 和 Login 显示登录的按钮位于主窗口 this Hide Login li new Login li Show 登录窗口上有一个检查密码的按钮 如果密码正确 我如何显示主窗口 将参数传递给 MainW
  • 0-1背包算法

    以下 0 1 背包问题是否可解 浮动 正值和 浮动 权重 可以是正数或负数 背包的 浮动 容量 gt 0 我平均有 这是一个相对简单的二进制程序 我建议用蛮力进行修剪 如果任何时候你超过了允许的重量 你不需要尝试其他物品的组合 你可以丢弃整
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • 如何引用解决方案之外的项目?

    我有一个 Visual Studio C 解决方案 其中包含一些项目 其中一个项目需要引用另一个不属于解决方案的项目 一开始我引用了dll
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • C++、三元运算符、std::cout

    如何使用 C 用三元运算符编写以下条件 int condition1 condition2 condition3 int double result int or double std cout lt lt condition1 resul
  • 带有私有设置器的 EFCore Base 实体模型属性 - 迁移奇怪的行为

    实体模型继承的类内的私有设置器似乎会导致 EFCore 迁移出现奇怪的问题 考虑以下示例 其中有多个类 Bar and Baz 继承自Foo 跑步时Add Migration多次命令 添加 删除private修饰符 生成的模式在多个方面都是

随机推荐

  • 如何使用JS下载视频标签?

    我有一个链接 我想从中下载视频
  • uitableview 在 iOS 中删除按钮图像

    我想更改 uitableview 单元格的滑动按钮图像 我已经搜索过了 但没有得到想要的结果 我用过这段代码 void willTransitionToState UITableViewCellStateMask state super w
  • 在一次调用中从多个表中选择

    在我的代码中 我有一个页面 其中包含来自 3 个不同表的信息 为了显示此信息 我进行了 3 个 SQL 选择调用 并将它们合并在一个列表中 以作为模型传递到我的视图 我可以通过一次 SQL 调用来完成此操作吗 数据之间没有任何联系 My c
  • 如何创建特定(R、G、B)颜色的 openCV 图像并获取该颜色名称?

    我需要创建一个填充一些 R G B 颜色的图像 并获得该颜色名称 例如 R G B 黑色或红色等 我们可以用 openCV 做这样的事情吗 如何做 具有静态方法的静态颜色图类 两个答案相结合 只需复制并使用即可 pragma once in
  • 按时间范围删除数据存储中的行

    我有一个 CKAN 数据存储 其中有一个名为 recvTime 的时间戳类型列 即在 datastore create 时使用 timestamp 作为类型 如这个链接所示 https github com telefonicaid fiw
  • 在php中从json_decode()获取值时出错?

    我有一个示例代码 description 2G Network GSM 850 900 1800 1900 3G Network HSDPA 850 900 1700 1900 2100 data json decode descripti
  • haskell中完整的缩进规则集

    从哪里可以获得 Haskell 代码编写的完整缩进规则集 过去的问题与我的以下问题类似 导致我提出上述问题 错误消息背后的原因是什么 parse error on input something 我收到的错误消息 Baby hs 103 2
  • 如何获取 git 中多个项目的任何分支中特定用户的提交列表?

    我在多个 git 项目的多个分支工作 我想获得所有这些项目和分支中特定日期的提交列表 用于时间表目的 虽然我可以为此目的编写实用程序脚本 但我不想重新发明轮子 有没有一种简单的方法可以使用现有的基于 UNIX 的工具或一些 git 高级用户
  • 选择两个 IP 范围之间的记录

    我有一张桌子 里面存放着ID Name Code IPLow IPHigh例如 1 Lucas 804645 192 130 1 1 192 130 1 254 2 Maria 222255 192 168 2 1 192 168 2 25
  • 将类型添加到 std 命名空间

    是否可以接受向std命名空间 例如 我想要一个 TCHAR 友好的字符串 那么以下可以接受吗 include
  • sass 无法编译,文件不可读或找不到

    转换错误 Jekyll Converters Sass 在转换时遇到错误 ng assets css all sass 找不到或无法读取要导入的文件 1 tools tools dir 1号线 这是我每次运行 Jekyll 时都会遇到的错误
  • 根据名称选择列表元素

    我有一个指定的向量列表 表示源自 2 个样本 A 和 B 的事件 l temp lt list SF1 t A c rep 1 10 SF2 t A c rep 9 15 SF1 t B c rep 8 12 l temp SF1 t A
  • 如何在 PDFSharp 中遍历 Pdf 对象树?

    我正在尝试使用 C 中的 PDFSharp 遍历现有 PDF 文档中的 PdfItem 对象树 我想创建一个所有对象的层次结构 类似于 PDF Explorer 示例所做的 但我希望它是一棵树而不是所有对象的平面列表 根节点是 docume
  • 函数模板的 typedef 的最佳替代方案?

    我想做的是这样的 template
  • Rails 5 Action Cable 与 Nginx、Puma 和 Redis 一起部署

    我正在尝试使用 Capistrano 将启用 Action Cable 的应用程序部署到 VPS 我正在使用 Puma Nginx 和 Redis 用于电缆 经过几个障碍后 我能够让它在本地开发环境中运行 我正在使用默认的进程内 cable
  • ASP.Net 6自定义WebApplicationFactory抛出异常

    我正在将现有的 ASP Net 5 Web 应用程序迁移到 ASP Net 6 并遇到了通过集成测试的最后障碍 我自定义 WebApplicationFactory 并抛出异常 Changing the host configuration
  • 打印浮点型/双精度型而不带尾随零? [复制]

    这个问题在这里已经有答案了 有几个与此相关的问题 但我还没有看到正确回答这个问题的人 我想打印一个浮点数 但我希望小数位数是自适应的 举个例子 0 gt 0 1234 gt 1234 0 1234 gt 0 1234 0 3 gt 0 3
  • Python pandas dataframe:找到另一列的每个唯一值的最大值

    我有一个大型数据框 从 500k 到 1M 行 其中包含例如这 3 个数字列 ID A B 我想过滤结果以获得如下图所示的表格 其中对于列 id 的每个唯一值 我都有 A 和 B 的最大值和最小值 我能怎么做 编辑 我已经更新了下面的图像以
  • 缩短 GCC 错误消息

    每当gcc无法找到具有多个重载的函数的匹配重载 它会给出一行又一行的错误 解释尝试了哪个重载以及为什么不使用它 虽然它通常很有用 但也常常没有用 因为问题是调用站点上的一个简单的拼写错误 在这种特殊情况下 它甚至没有帮助 因为甚至需要相当长
  • 如何通过比较两个 C# 对象来创建 JsonPatchDocument?

    鉴于我有两个相同类型的 C 对象 我想比较它们以创建 JsonPatchDocument 我有一个 StyleDetail 类定义如下 public class StyleDetail public string Id get set pu