【ASP.NET Core】JSON Patch 使用简述
JSON Patch 是啥玩意儿?不知道,直接翻译吧,就叫它“Json 补丁”吧。干吗用的呢?当然是用来修改 JSON 文档的了。那咋修改呢?比较常见有四大操作:AMRR。
咋解释呢?
A—— Add;
M—— Move;
R—— Replace;
R—— Remove。
Add 就是向 JSON 对象中添加一对 key - value,或者向 Json Array 中加个元素。
Move 就是把某个节点从一个地方移到另一个地方。
Replace 就是替换,比如把 city 的值从“广州”改为“珠海”。
Remove 就是删除 JSON 对象中的某对 key - value,或者从 Json Array 中删除一个元素。
除了上述四大美女外,还有 copy,就是把某个节点复制到另一个地方;test 这个嘛,在修改 JSON 文档之前验证某个值,如果值正确了就进行更新,如果值不对就“呵呵“,比如,可以 test 一下 age 属性是否为 25,如果是就更新 SON 文档,如果不是就算了吧。
这个 JSON Patch 也不是很复杂,你可以参考主页上的说明,主页地址:http://jsonpatch.com/
这个 JSON Patch 有什么用呢?有用得很!尤其是现在很多数据都是通过网络来传输的,而且许多数据也喜欢用 JSON 格式(貌似是比 XML 简单一些)。如果 JSON 文档比较长,客户端获取了数据后,然后可能会对数据进行更新,然后更新时又把整个 JSON 文档提交回服务器。虽然这一来一回,所产生的流量远不如你打《王者农药》所产生的流量,但是,如果传输频繁,这个流量消耗也是不小的,毕竟各大运营商是增不降费的。按照现在各种破 App 内含数不胜数的虚假广告和一些无用的图片信息,刷几条微博就刷掉 5-6 M 的流量了。
所以说,尽量减少传输量是很有必要的。JSON Patch 不必把整个 JSON 文档都提交回服务器,而仅告诉服务器你要更新哪个地方就好了。比如
[ { "op" : "add", "path" : "/age", "value" : "150" }, { "op" : "replace", "path" : "/name", "value" : "老鬼" } ]
注意,JSON Patch 本质上也是一个 JSON 文档。在写的时候,要记得最外面有一层中括号,为啥?你都看到了,是个数组。因为你可以同时把多个操作组合在一起提交。就像上面的,add 和 replace 操作就一起提交了。
当然了,老周本文重点是介绍如何在 ASP.NET Core 中使用 JSON Patch 的,所以,下面咱们切入正题,不说 F 话了。
ASP.NET Core 的 API 自身也有与 JSON Patch 相关的实现,所以,用起来还是挺省心的。这些 API 都分布在 Microsoft.AspNetCore.JsonPatch.* 命名空间中。
相当核心的一个类就是 JsonPatchDocument<TModel>,TModel 是指你要用来生成 JSON 文档的模型类。当客户端提交 JSON Patch 上来后,会自动包含在该对象上,然后你只要调用一下 AppliyTo 方法就可以对模型对象进行更新了。
非常简单的,下面老周就给你演示一下。这里我用的 Web API ,因为这一情形是最为常用的。模型对象是一个字典实例—— IDictionary<string, object>,之所以用字典,是因为字典比较好添加属性。
添加一个 API 控制器类,然后初始化一个字典实例。
[Route("api/[controller]")] public class DemoController : Controller { IDictionary<string, object> dic = new Dictionary<string, object> { ["name"] = "非洲黑鹿", ["age"] = 35, ["phone"] = "19929939900" }; }
为了可以获取数据,可以定义一个 HTTP-GET 方法访问的方法,并将字典以 JSON 文档返回。
[HttpGet("pick")] public IActionResult PickData() { return Json(dic); }
下面来重点了,为了能够使用 JSON Patch 来更新字典对象,还要弄一个以 HTTP-POST 方法提交的方法。
[HttpPost("set")] public IActionResult SetData([FromBody]JsonPatchDocument<IDictionary<string,object>> body) { body.ApplyTo(dic); return Json(dic); }
请严重注意:
1、方法参数的类型是 JsonPatchDocument<TModel>,这样服务器收到客户端提交的 JSON Patch 文档后会自动创建 JsonPatchDocument 实例并传递给 body 参数。
2、在参数上要应用 FromBodyAttribute (特性),因为你得告诉运行时,客户端 POST 上来的整个数据正文将用于生成 JSON Patch 文档。
3、更新字典实例很简单,直接调用 JSON Patch 文档的 ApplyTo 方法就完事了。
好了,就是这么简单,这个演示的例子就完工了。不过得打开 Program.cs 文件,配置一下 Host。
public static void Main(string[] args) { WebHostBuilder bd = new WebHostBuilder(); bd.UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup<Startup>() .UseUrls("http://*:6000") .UseKestrel(); var host = bd.Build(); host.Run(); }
http://*:6000 表示应用程序的 URL 在 6000 端口上侦听连接,* 表示绑定给本机的任意主机名。比如 localhost。
在 Startup 类中,还要配置 MVC 的内容,Web API 其实也是 MVC 的一种,只是它不返回 HTML 。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app) { app.UseMvc(); }
由于刚才在 DemoController 控制器中已经用了路由特性指定了路由规则,那么这里就不用再配置全局路由规则了。
[Route("api/[controller]")]
好,现在我们来测试一下。测试 API 可以用 Postman 大叔,因为它比较牛。
首先,输入 URL http://localhost:6000/api/demo/pick,方式为 GET。
然后返回以下数据。
现在,我们把里面的 name 属性改为“巴西龟”。输入 URL http://localhost:6000/api/demo/set,提交方式为 POST。
选择 “body” ,格式选 raw,Content Type 选 JSON ( application / json )。
然后输入以下 JSON 。
[ { "op" : "replace", "path" : "/name", "value" : "巴西龟" } ]
提交之后,得到更新后的字典数据。
我们还可以进行多个操作,除了修改 name 的值,还可以考虑添加一个项。
[ { "op" : "replace", "path" : "/name", "value" : "巴西龟" }, { "op" : "add", "path" : "/email", "value" : "small-pig@163.com" } ]
向字典添加一个 email 字段。
发送请求后,返回字典数据的最新内容。
好了,简单的演示就结束了。
最后,老周还要强调一点,就是如果你的 JSON Patch 文档的 TModel 是一个类,由于 .NET 是面向对象的,你不能随便向一个类添加属性,因此,add 操作对于类是不可行的,但你可以进行 replace 操作。
=============================
前两天,也就是上个星期六,由于张老鬼找老周有点事情研究,所以【闲聊 ASP.NET Core】的直播暂停一次。这个星期可以补上,周六周日都行,到时候老周会在微博上发一下时间,因为这个周末,女朋友所在的公司组织全体员工去长途旅游,所以这个周末老周就可以自由了,爱干吗就干吗。
我们俩都是穷人家的孩子,双方都没有车,距离又有点远,每次见面都要滴滴打车,所以一个月也只能见两三次面。这个五月她那边比较忙,只见了一次面。没办法,想天天去浪是不可能的了。这就是咱们平头百姓的生活。