热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

jsonpacth中文文档(纯机翻如侵权请联系删除)

使用ASP.netCore的JSON补丁2017年11月29日由韦德8评论JSONPatch是一种以非常明确的方式更新API上的文档的方法。它本质上是一个合同,用于准
使用ASP.net Core的JSON补丁
2017年11月29日由韦德 · 8评论
JSONPatch是一种以非常明确的方式更新API上的文档的方法。它本质上是一个合同,用于准确描述您希望如何修改文档(例如,将字段中的值替换为另一个值),而不必同时发送其余未更改的值。

JSON补丁请求是什么样的?

JSON Patch的官方文档存在于这里:http:  //jsonpatch.com/,但我们将进行一些挖掘,以了解它在ASP / C#中的工作原理,因为并非所有应用程序都能正常工作。事实上,一项操作还没有成为ASP.net Core的正式版本,但无论如何我们都会快速谈谈它。
对于所有示例,我将针对在C#中看起来像这样的对象编写JSON补丁请求:
1
2
3
4
5
6
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List Friends { get; set; }
}
补丁请求都遵循类似的结构类型。它是数组中“操作”的列表。该操作本身有3个属性。
“op” - 定义您要执行的操作的“类型”。例如,添加,替换,测试等
“path” - 要编辑的对象上属性的“路径”。在上面的示例中,如果我们想要编辑“FirstName”,则“path”属性看起来像“/ firstname”
“value” - 在大多数情况下,定义我们想要在操作中使用的值。
现在让我们来看看每个单独的操作。

添加操作通常意味着您要向对象添加属性或将项“添加”到数组中。对于前者,这在C#中不起作用。因为C#是强类型语言,所以不能将属性“添加”到编译时尚未定义的对象上。
要将项添加到数组中,请求将如下所示:
1
{ "op": "add", "path": "/Friends/1", "value": "Mike" }
这将在Friends数组中的索引1处“插入”“Mike”的值。或者,您可以使用“ - ”字符在数组末尾插入记录。
1
{ "op": "add", "path": "/Friends/-", "value": "Mike" }

 

去掉

与上面概述的“添加”操作类似,“删除操作”通常表示您要么从对象中删除属性,要么从数组中删除项目。但是因为你实际上无法从C#中的对象“移除”属性,实际发生的是它会将值设置为默认值(T)。在某些情况下,如果对象可以为空(或引用类型),则将其设置为NULL。但要小心,因为当在值类型上使用时,例如int,那么该值实际上会重置为“0”。
要在对象属性上运行Remove以“重置”它,您将运行以下命令:
1
{ "op": "remove", "path": "/FirstName"}
您还可以运行“删除”操作以删除阵列中的特定项目
1
{ "op": "remove", "path": "/Friends/1" }
这将从数组索引1中删除该项。没有这样的“where”子句用于删除或删除所以有时这对于从这样的数组索引中删除项目似乎非常危险,因为如果数组自我们获取后发生了更改它来自服务器?实际上有一个JSON Patch操作可以帮助解决这个问题,但稍后会有更多内容。

更换

替换完全符合它在锡上的说法。它取代了另一个的任何价值。这可以用于对象的简单属性:
1
{ "op": "replace", "path": "/FirstName", "value": "Jim" }
它还可以替换数组项中的特定属性:
1
{ "op": "replace", "path": "/Friends/1", "value": "Bob" }
它也可以替换整个对象/数组,如下所示:
1
{ "op": "replace", "path": "/Friends", "value": ["Bob", "Bill"] }

 

复制

复制会将值从一个路径移动到另一个路径。这可以是属性,对象,数组等。在下面的示例中,我们将Firstname的值移动到LastName。实际上,这并不是很多,因为你通常会看到两个属性的简单替换而不是副本,但它是可能的!如果您真正深入了解JSON Patch的ASP.net核心实现的源代码,您将看到复制操作简单在路径的后台执行“添加”操作。
1
{ "op": "copy", "from": "/FirstName", "path" : "/LastName" }

 

移动

Move操作与Copy非常相似,但正如它在tin上所说,该值将不再位于“from”字段。这是另一个,如果你看看ASP.net Core的底层,它实际上在from字段上删除,并在Path字段上添加。
1
{ "op": "move", "from": "/FirstName", "path" : "/LastName" }

 

测试

测试操作目前不存在于ASP.net Core的公开发行版中,但是如果你在Github上检查源代码,你可以看到它已经被微软处理,应该进入下一个版本。测试几乎是一种执行乐观锁定的方法,或者更简单地说是检查自检索数据以来服务器上的对象是否已更改。
考虑以下完整补丁:
1
2
3
4
[
{ "op": "test", "path": "/FirstName", "value": "Bob" }
{ "op": "replace", "path": "/FirstName", "value": "Jim" }
]
这就是说,首先检查“/ FirstName”路径上的值是Bob,如果是,则将其更改为Jim。如果该值不是Bob,则不会发生任何事情。需要注意的一点是,您可以在单个修补程序有效内容中执行多个测试操作,但如果其中任何一个测试失败,则不会应用整个修补程序。

但是为什么JSON补丁呢?

显然,JSON Patch的一大优势在于它的有效载荷非常轻巧,只能准确发送对象上发生的变化。但是在ASP.net Core中还有另一个很大的好处,它实际上有一些很好的用途,唯一的原因是C#是一种打字语言。没有好的例子,很难解释。所以想象一下我从API请求一个“Person”对象。在C#中,模型可能如下所示:
1
2
3
4
5
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
当从API作为JSON对象返回时,它看起来像这样:
1
2
3
4
{
"firstName" : "James",
"lastName" : "Smith"
}
现在从前端开始,不使用JSON补丁,我决定只需要更新名字,所以我发回以下有效负载:
1
2
3
{
"firstName" : "Jim"
}
现在,当我在C#中反序列化此模型时,问题就出现了。没有看下面。我们的模型的价值是什么?
1
2
3
4
5
public class Person
{
public string FirstName { get; set; } //Jim
public string LastName { get; set; } //
}
嗯。因为我们没有通过LastName发送它,它被序列化为Null。但这很简单,我们可以忽略null的值,并在我们的数据层上做一些挑剔的事情,只更新我们实际传递的字段。但这不一定是真的,如果该字段实际上可以为空呢?如果我们通过以下有效负载发送了怎么办
1
2
3
4
{
"firstName" : "Jim",
"lastName" : null
}
所以现在我们实际上已经指定我们想要取消该字段。但是因为C#是强类型的,所以我们无法在服务器端确定有效负载中缺少的值与使用标准模型绑定实际设置为null的值相比。
这似乎是一个奇怪的场景,因为前端可以始终发送完整的模型,永远不会省略字段。在大多数情况下,前端Web库的模型将始终与API的模型匹配。但有一种情况并非总是如此,那就是移动应用程序。通常在提交移动应用程序来说Apple App Store时,可能需要数周时间才能获得批准。在这个时候,您可能还有需要推出的Web或Android应用程序才能使用新模型。在不同平台之间实现同步非常困难,而且往往是不可能 虽然API版本确实可以解决这个问题,但我仍然认为JSON Patch在以稍微不同的方式解决这个问题方面具有很大的实用性。
最后,它就到了这一点!考虑Person对象的以下JSON Patch有效负载:
1
2
3
4
5
6
7
[
{
"op": "replace",
"path": "/firstName",
"value": "Jim"
}
]
这明确表示我们想要更改名字而不是其他任何名称。从来没有模棱两可的“我们只是忘记发送该财产,还是我们真的希望它'被淘汰'”。它是精确的,并准确地告诉我们将要发生什么。

将JSON补丁添加到您的ASP.net核心项目中

在Visual Studio内部,从程序包管理器控制台运行以下命令以安装官方JSON补丁程序库(在新项目中没有开启ASP.net Core)。
1
Install-Package Microsoft.AspNetCore.JsonPatch
对于此示例,我将使用以下完整控制器。要注意的要点是我们使用的HTTP Verb是“Patch”,我们接受一种类型的“JsonPatchDocument ”并且“应用”我们在补丁上简单地称为“ApplyTo”的更改并传入对象我们想要更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Route("api/[controller]")]
public class PersonController : Controller
{
private readonly Person _defaultPerson = new Person
{
FirstName = "Jim",
LastName = "Smith"
};
[HttpPatch("update")]
public Person Patch([FromBody]JsonPatchDocument personPatch)
{
personPatch.ApplyTo(_defaultPerson);
return _defaultPerson;
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
在我们的示例中,我们只是使用存储在控制器上的简单对象并对其进行更新,但在实际的API中,我们将从数据源中提取数据,应用补丁,然后将其保存回来。
当我们使用以下有效负载调用此端点时:
1
2
3
[
{"op" : "replace", "path" : "FirstName", "value" : "Bob"}
]
我们得到的回应是:
1
2
3
4
{
"firstName": "Bob",
"lastName": "Smith"
}
真棒!我们的名字改为鲍勃!使用JSON Patch启动和运行真的很简单。

生成补丁

许多人问的第一个问题是他们应该如何制作他们的JSON Patch有效载荷。您不必手动执行此操作!有许多Javascript库可以“比较”两个对象以生成补丁。更简单的是,有许多可以“观察”对象并按需生成补丁。JSON Patch网站有一个很好的入门库列表:http:  //jsonpatch.com/

使用带有JSON补丁的Automapper

我经常在JSON Patch周围看到的一个重要问题是,您经常从API返回View Models / DTO,并从那里生成补丁。但是,那么如何将这些补丁应用回数据库对象?人们倾向于过度思考并创建疯狂的“变换”以将补丁从一个对象转换到另一个对象,但是使用Automapper的一种更简单的方法是非常简单。代码的工作原理如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[HttpPatch("update/{id}")]
public Person Patch(int id, [FromBody]JsonPatchDocument personPatch)
{
PersonDatabase personDatabase = _personRepository.GetById(id); // Get our original person object from the database.
PersonDTO personDTO = _mapper.Map(personDatabase); //Use Automapper to map that to our DTO object.
personPatch.ApplyTo(personDTO); //Apply the patch to that DTO.
_mapper.Map(personDTO, personDatabase); //Use automapper to map the DTO back ontop of the database object.
_personRepository.Update(personDatabase); //Update our person in the database.
return personDTO;
}
需要注意的一点是,在第二次Map调用中将DTO映射回Database对象时,Automapper有一个很好的功能,它可以映射到现有对象,只映射它关心的字段。数据库对象上的任何其他字段将保持不变。
如果您需要设置Automapper的帮助,请查看我们关于在ASP.net Core中使用Automapper的精彩教程  。

转:https://www.cnblogs.com/gaoliangchao/p/10037039.html



推荐阅读
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
author-avatar
我以为我疯叻_219
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有