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】的直播暫停一次。這個星期可以補上,周六周日都行,到時候老周會在微博上發一下時間,因為這個周末,女朋友所在的公司組織全體員工去長途旅游,所以這個周末老周就可以自由了,愛干嗎就干嗎。
我們倆都是窮人家的孩子,雙方都沒有車,距離又有點遠,每次見面都要滴滴打車,所以一個月也只能見兩三次面。這個五月她那邊比較忙,只見了一次面。沒辦法,想天天去浪是不可能的了。這就是咱們平頭百姓的生活。