如何在ASP.NET Core中使用JSON Patch

原文: JSON Patch With ASP.NET Core

作者:.NET Core Tutorials

译文:如何在ASP.NET Core中使用JSON Patch

地址:https://www.cnblogs.com/lwqlun/p/10433615.html

译者:Lamond Lu

640?wx_fmt=jpeg

JSON Patch是一种使用API显式更新文档的方法。它本身是一种契约,用于描述如何修改文档(例如:将字段的值替换成另外一个值),而不必同时发送其他未更改的属性值。

一个JSON Patch请求是什么样的?

你可以在以下链接(http://jsonpatch.com/)中找到JSON Patch的官方文档,但是这里我们将进一步研究一下如何在ASP.NET Core中实现JSON Patch。

为了演示JSON Patch, 我创建了以下C#对象类, 后续我将使用JSON Patch请求来操作这个对象类的实例。


public class Person
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public List<string> Friends { get; set; }
}

每个JSON Patch请求都是遵循一个相似的结构。它有一个固定的“操作”列表。每个操作本身拥有3个属性:

  • "op" - 定义了你要执行何种操作,例如add, replace, test等。

  • "path" - 定义了你要操作对象属性路径。用前面的Person类为例,如果你希望修改FirstName属性,那么你使用的操作路径应该是"/FirstName"。

  • "value" - 在大部分情况下,这个属性表示你希望在操作中使用的值。

现在让我们来看一下每一个的操作如何使用。

Add

Add操作通常意味着你要向对象中添加属性,或者向数组中添加项目。对于前者,在C#中是没有用的,因为C#是强类型语言,所以不能将属性添加到编译时尚未定义的对象上。

所以这里如果想往数组中添加项目,PATCH请求的内容应该如下所示。

{ "op": "add", "path": "/Friends/1", "value": "Mike" }

这将在Friends数组的索引1处插入一个"Mike"值。

或者你还可以使用"-"在数组尾部插入记录。

{ "op": "add", "path": "/Friends/-", "value": "Mike" }

Remove

与Add操作类似,删除操作意味着你希望删除对象中属性,或者从数据中删除某一项。但是因为在C#中你无法移除属性,实际操作时,它会将属性的值变更为default(T)。在某些情况下,如果属性是可空的,则会设置属性值为NULL。但是需要小心,因为当在值类型上使用时,例如int, 则该值实际上会重置为"0"。

如果要在对象上删除某一属性以达到重置的效果,你可以使用一下命令。

{ "op": "remove", "path": "/FirstName"}

当然你也可以使用删除命令删除数组中的某一项。

{ "op": "remove", "path": "/Friends/1" }

这将删除数组索引为1的项目。但是有时候使用索引从数组中删除数据是非常危险的,因为这里没有一个"where"条件来控制删除, 有可能在删除的时候,数据库中对应数组已经发生变化了。实际上有一个JSON Patch操作可以帮助解决这个问题,后面我会描述它。

Replace

Replace操作和它的字面意思完全一样,可以使用它来替换已有值。针对简单属性,你可以使用如下的命令。

{ "op": "replace", "path": "/FirstName", "value": "Jim" }

你同样可以使用它来替换数组中的对象。

{ "op": "replace", "path": "/Friends/1", "value": "Bob" }

你甚至可以用它来替换整个数组。

{ "op": "replace", "path": "/Friends", "value": ["Bob", "Bill"] }

Copy

Copy操作可以将值从一个路径复制到另一个路径。这个值可以是属性,对象,或者数据。在下面的例子中,我们将FirstName属性的值复制到了LastName属性上。这个命令的使用场景不是很多。

{ "op": "copy", "from": "/FirstName", "path" : "/LastName" }

Move

Move操作非常类似于Copy操作,但是正如它的字面意思,"from"字段的值将被移除。如果你看一下ASP.NET Core的JSON Patch的底层代码,你会发现,它实际上它会在"from"路径上执行Remove操作,在"path"路径上执行Add操作。

{ "op": "move", "from": "/FirstName", "path" : "/LastName" }

Test

在当前的ASP.NET Core公开发行版中没有Test操作,但是如果你在Github上查看源代码,你会发现微软已经处理了Test操作。Test操作是一种乐观锁定的方法,或者更简单的说,它会检测数据对象从服务器读取之后,是否发生了更改。

我们以如下操作为例。

[
{ "op": "test", "path": "/FirstName", "value": "Bob" }
{ "op": "replace", "path": "/FirstName", "value": "Jim" }
]

这个操作首先会检查"/FirstName"路径的值是否"Bob", 如果是,就将它改为"Jim"。 如果不是,则什么事情都不会发生。这里你需要注意,在一个Test操作的请求体内可以包含多个Test操作,但是如果其中任何一个Test操作验证失败,所以的变更操作都不会被执行。

为什么要使用JSON PATCH

JSON Patch的一大优势在于它的请求操作体很小,只发送对象的更改内容。 但是在ASP.NET Core中使用JSON Patch还有另一个很大的好处,就是C#是一种强类型语言,无法区分是要将模型的值设置为NULL,还是忽略该属性, 而使用JSON Patch可以解决这个问题。

这里如果没有好的例子,很难解释。 所以想象一下我从API请求一个“Person”对象。 在C#中,模型可能如下所示:


public class Person
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

当从API返回Json对象时,它看起来可能像这样。

{
"firstName" : "James",
"lastName" : "Smith"
}

现在在前端,如果不使用JSON Patch, 如果我只想更新FirstName, 我可能在请求中附带一下请求体。

{
"firstName" : "Jim"
}

现在当我在C#中反序列化这个模型时,问题就出现了。不要看下面的代码,想一下此时我们的模型中的属性值是什么?

public class Person
{
   public string FirstName { get; set; } //Jim
   public string LastName { get; set; } //<Null>
}

因为我们发送LastName属性的值,所以它被反序列化为Null。 但这很简单,我们可以忽略NULL的值,只更新我们实际传递的字段。 但这不一定是正确的,如果该字段实际上可以为空呢? 如果我们发送了以下请求体怎么办?

{
"firstName" : "Jim",
"lastName" : null
}

所以现在我们实际上已经指定我们想要取消该字段。但是因为C#是强类型的,所以我们无法在服务器端进行模型绑定的时候,我们无法确定它是否要将该字段的值设置为NULL。

这似乎是一个奇怪的场景,因为前端可以始终发送完整的数据模型,永远不会省略字段。并且在大多数情况下,前端Web库的模型将始终与API的模型匹配。但有一种情况并非如此,那就是移动应用程序。通常向苹果应用商店提交手机应用,可能需要数周时间才能获得批准。在这个时候,你可能还需要在Web或Android应用程序中使用新模型。在不同平台之间实现同步非常困难,而且通常是不可能。虽然API版本确实对解决这个问题有很长的路要走,但我仍然认为JSON Patch在解决这个问题方面具有很大的实用性。

最后,让我们使用JSON Patch!我们可以使用以下JSON Patch请求更新Person对象

[
  {
     "op": "replace",
     "path": "/FirstName",
     "value": "Jim"
  }
]

这明确表示我们想要更改名字而不是其他内容。 它准确的告诉我们到底将要发生什么。

在ASP.NET Core项目中启用JSON Patch

在Visual Studio中,我们可以在Package Manage Console中安装官方的Json Patch库(默认创建的ASP.NET Core项目中没有该库)。

Install-Package Microsoft.AspNetCore.JsonPatch

为了演示,我将添加如下的一个控制器类。这里需要注意我们使用的HTTP verb是HttpPatch, 请求参数的类型是JsonPatchDocument<T>。 为了更新对象,我们只需要简单调用ApplyTo方法,并传入了需要更新的对象。640?wx_fmt=png

在以上示例中,我们只是使用了存放在控制器中的简单对象并对其进行了更新,但是在正式的API中,我们需要从数据库中拉取数据对象,更新对象,并重新保存到数据库。

当我们使用如下请求体发送JSON Patch请求时:

[
{"op" : "replace", "path" : "/FirstName", "value" : "Bob"}
]

我们可以得到如下响应内容:

{
   "firstName": "Bob",
   "lastName": "Smith"
}

真棒! 我们的名字改为Bob! 使用JSON Patch启动和运行真的很简单。

使用Automapper处理JSON Patch请求

针对JSON Patch的使用,最大的问题是,你经常需要从API返回View Model或者DTO, 并生成PATCH请求。但是如果将这些修改请求应用于数据库对象上?大部分情况下,开发人员都挣扎在与此。这里我们可以使用Automapper来帮助完成这个转换的工作。

例如如下代码:

640?wx_fmt=png




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317014.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET Core RSA密钥的xml、pkcs1、pkcs8格式转换和JavaScript、Java等语言进行对接

众所周知在.NET下的RSA类所生成的密钥为Xml格式&#xff0c;而其他语言比如java一般使用pkcs8格式的密钥&#xff0c;JavaScript一般使用pkcs1格式。我们在开发过程中很可能遇到需要与其他语言开发的api进行对接&#xff0c;如果遇到RSA加密解密&#xff0c;我们肯定需要保证ke…

ABP VNext 微服务演示,项目状态和路线图

在ABP vNext上的第一个公告之后,我们对代码库进行了很多改进(GitHub存储库上的1100多次提交).我们已经创建了功能,示例,文档等等.在这篇文章中,我想告诉你一些新闻和项目的状态.ABP微服务演示解决方案ABP框架的主要目标之一是提供创建微服务解决方案的便利基础设施.我们一直在努…

[aspnetcore.apidoc]一款很不错的api文档生成工具

简单徐速一下为什么选用了aspnetcore.apidoc 而没有选用swagger最初我们也有在试用swagger&#xff0c;但总是有些感觉&#xff0c;感觉有点不满意&#xff0c;就但从api文档角度来说&#xff0c;从前后端文档沟通角度来讲apidoc的表现形式&#xff0c;要比swagger简单的多&…

Acwing1069. 凸多边形的划分

Acwing1069. 凸多边形的划分 题意&#xff1a; 一个N个顶点的凸多边形&#xff0c;划分成N-2个互不相交的三角形&#xff0c;对于每个三角形&#xff0c;其三个顶点的权值相乘都可得到一个权值乘积&#xff0c;试求所有三角形的顶点权值乘积之和至少为多少。 题解&#xff1…

徐磊(Devops):一名写了十几年代码但还没写够的程序员

徐磊&#xff08;Devops 社区领袖&#xff09;【个人介绍】徐磊&#xff0c;微软MVP&#xff08;微软最有价值专家&#xff0c;大中华区域社区技术总监&#xff0c;Devops 社区领袖&#xff09;&#xff0c;从事过网管、技术支持、网络、软件开发等工作&#xff0c;一名写了十几…

AcWing 320. 能量项链

AcWing 320. 能量项链 题意&#xff1a; 题解&#xff1a; 和环形石头合并基本一样 代码&#xff1a; #include<bits/stdc.h> #define debug(a,b) printf("%s %d\n",a,b); typedef long long ll; using namespace std;inline int read(){int s0,w1;char c…

ERP不规范,同事两行泪

最近的很多次对外交流&#xff0c;都聊到了ERP建设的话题&#xff0c;并且无一例外的不那么让人省心&#xff0c;回想我这么多年走过的ERP坑坑路&#xff0c;在这里也写下经验和总结&#xff0c;希望能给正在或者即将走上ERP建设路的企业一些思考和帮助。导读1、几个瞎眼而普遍…

长沙.NET社区之光

奈何万事开头难迎着改革开放四十年带来的春风&#xff0c;长沙的互联网生态环境以唐胡子俱乐部为首的一众互联网社群将长沙互联网的环境推上了一个新的台阶。年底&#xff0c;我与有幸一起共事的溪源兄&#xff0c;下班后一起闲聊&#xff0c;觉着长沙的.NET的生态环境亟待改善…

高级进阶:Azure DevOps搞定.NET Core编译版本号自增

点击上方蓝字关注“汪宇杰博客”熟悉.NET Framework的人知道&#xff0c;我们可以通过指定AssemblyVersion为10.0.*来让编译器自增版本号。但是.NET Core和.NET Standard不行。即使有MSBump这样的开源项目&#xff0c;也有一定的缺陷。一般这样的需求会出现在CI/CD服务器上。我…

Newbe.Claptrap - 一套以 “事件溯源” 和“Actor 模式”作为基本理论的服务端开发框架...

本文是关于 Newbe.Claptrap 项目主体内容的介绍&#xff0c;读者可以通过这篇文章&#xff0c;大体了解项目内容。轮子源于需求随着互联网应用的蓬勃发展&#xff0c;相关的技术理论和实现手段也在被不断创造出来。诸如 “云原生架构”、“微服务架构”、“DevOps” 等一系列关…

NET Core微服务之路:SkyWalking+SkyApm-dotnet分布式链路追踪系统的分享

对于普通系统或者服务来说&#xff0c;一般通过打日志来进行埋点&#xff0c;然后再通过elk或splunk进行定位及分析问题&#xff0c;更有甚者直接远程服务器&#xff0c;直接操作查看日志&#xff0c;那么&#xff0c;随着业务越来越复杂&#xff0c;企业应用也进入了分布式服务…

Tree UVALive - 8212

Tree UVALive - 8212 题意&#xff1a; 有n个点&#xff0c;k个颜色&#xff0c;每个点都要被染色&#xff0c;相同颜色之间的边算是被该颜色覆盖&#xff0c;问有多少边被所有颜色覆盖 题解&#xff1a; 题目给的是无根树&#xff0c;我们可以将1默认为根然后求所有点的子…

dotnetcore-officeaddin-toolbox : Office 365 Add-in开发人员的工具箱

在上一篇文章&#xff08;.NET Core开源行动&#xff1a;一键创建Excel Add-in&#xff09; 中我给大家展示了一套为Office 365 Add-in开发人员准备的模板库&#xff0c;你可以通过 dotnet new excel & dotnet run 命令即可完成一个新的Add-in的创建和运行。关于如何加载这…

Asp.Net Core对接钉钉群机器人

钉钉作为企业办公越来越常用的软件&#xff0c;对于企业内部自研系统提供接口支持&#xff0c;以此来打通多平台下的数据&#xff0c;本次先使用最简单的钉钉群机器人完成多种形式的消息推送&#xff0c;参考钉钉开发文档中自定义机器人环节&#xff0c;此次尝试所花的时间不多…

转录组无参比对教程

写在前面 2023年将结束&#xff0c;小杜的生信笔记分享个人学习笔记也有2年的时间。在这2年的时间中&#xff0c;分享算是成为工作、学习和生活中的一部分。自己为了运行和维护社群也算花费大量的时间和精力&#xff0c;自己认为还算满意吧。对于个人来说&#xff0c;自己一直…

.NET Core开源行动:一键创建Excel Add-in

作为.NET Core开源行动的一部分&#xff0c;我此前已经创建和发布了一套基于.NET Core的Office 365开发模板库&#xff0c;是针对Microsoft Graph开发的场景的&#xff0c;有兴趣可以参考 https://github.com/chenxizhang/dotnetcore-office365dev-templates-msgraph &#xff…

【学习笔记】最小生成树系列的必做经典题

最小生成树系列【模板】最小生成树prim算法kruskal算法Borůvka (Sollin)算法次小生成树最小生成树计数最优比率生成树最小乘积生成树最小度限制生成树最小方差树【模板】最小生成树 prim算法 最小生成树的prim\text{prim}prim类似于最短路的dijkstra\text{dijkstra}dijkstra…

通过 Azure Pipelines 实现持续集成之docker容器化

IntroAzure DevOps Pipeline 现在对于公开的项目完全免费&#xff0c;这对于开源项目来讲无疑是个巨大的好消息&#xff0c;在 Github 的 Marketplace 里有个 Azure Pipeline&#xff0c;就是微软的 Azure DevOps Pipeline。实现 Docker 容器化的持续集成实现的目标&#xff1a…

Acwing 1082. 数字游戏

Acwing 1082. 数字游戏 题意&#xff1a; 现在大家决定玩一个游戏&#xff0c;指定一个整数闭区间 [a,b]&#xff0c;问这个区间内有多少个不降数。 题解&#xff1a; 利用数位dp的套路来做 我们还是利用前缀和来做 我们先求1~n中满足情况的个数 对于一个n位数&#xff0c;…

【招聘(南京)】南京纳龙科技有限公司招高级.net开发工程师

南京纳龙科技有限公司成立于2002年12月&#xff0c;隶属纳龙科技在南京成立的研发中心&#xff0c;坐落于南京市雨花台区。公司立志以守护人类心脏健康为使命&#xff0c;专注推动心电信息化技术的发展&#xff0c;为全国各级医疗机构提供心电检查、诊断一体化的解决方案。公司…