JSON Patch

来源:https://www.cnblogs.com/Wddpct/archive/2018/05/15/9039466.html
-Advertisement-
Play Games

1.前言 可以這麼說的是,任何一種非強制性約束同時也沒有“標桿”工具支持的開發風格或協議(僅靠文檔是遠遠不夠的),最終的實現上都會被程式員冠上“務實”的名頭,而不管成型了多少個版本,與最初的設計有什麼區別。DDD 是如此,微服務是如此,REST 也是如此。 雖然這也不難理解,風格從一開始被創造出來後 ...


1.前言

可以這麼說的是,任何一種非強制性約束同時也沒有“標桿”工具支持的開發風格或協議(僅靠文檔是遠遠不夠的),最終的實現上都會被程式員冠上“務實”的名頭,而不管成型了多少個版本,與最初的設計有什麼區別。DDD 是如此,微服務是如此,REST 也是如此。

雖然這也不難理解,風格從一開始被創造出來後,便不再屬於作者了。所以仍然把你的符合以下標準

  • 滿足以資源形式定義定義 Uri
  • 滿足以 HTTP 謂詞語義增刪改查資源
  • 符合命名要求
  • ……

的“不標準” Web API 看作是 RESTful 的,也未嘗不可。畢竟,誰在乎呢?

更深層次的討論參見Why Some Web APIs Are Not RESTful and What Can Be Done About It。什麼才是真正的 REST Api 並不是本文的重點(Github Rest API v3),筆者在後文討論的具體實現,也只是符合目前流行的“RESTful”直覺設計。

2. HTTP 謂詞

謂詞 釋義 冪等性 安全性
HEAD 用於獲取資源的 HTTP Header 信息
GET 用於檢索信息
POST 用於創建資源
PUT 用於更新或替換完整資源或批量更新集合。對於沒有 Body 的 PUT 動作,請將 Content-Length 設置為 0
DELETE 用於刪除資源
PATCH 用於使用部分 JSON 數據更新資源信息(在一個請求里可搭載多個動作)。PATCH 是一個相對較新的 HTTP 謂詞,在客戶端或伺服器不支持 PATCH 動作時,也可以使用 Post/Put 更新資源

3. PATCH & JSON Patch

結合上述 HTTP 謂詞,通常情況下,更新部分資源的部分數據時,有以下四種做法:

  1. 使用 PUT 謂詞, 儘可能使用完整對象來更新資源(即根本不使用 PATCH )。
  2. 使用 JSON Merge Patch 更新部分資源的部分數據(需要使用指定 MIME application/merge-patch+json 來表示)。
  3. 使用 PATCH 謂詞和 JSON Patch(需要使用指定 MIME application/json-patch+json 來表示)
  4. 如果請求不以 MIME 的語義定義的方式修改資源,使用具有合理描述的 POST 謂詞。

我相信大部分系統中,採取的都是第1種和第4種做法,而本文的主題則是第3種做法。

RFC 5789(PATCH method for HTTP) 中,有一個關於 PATCH 請求的小例子:

PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100

[description of changes]

[description of changes] 代表對目標資源的一系列操作,而JSON Patch則是描述操作的文檔格式。


// 示例 json 文檔
{
    "a":{
        "b":{
            "c":"foo"
        }
    }
}

// JSON Patch 操作
[
  { "op": "test", "path": "/a/b/c", "value": "foo" },
  { "op": "remove", "path": "/a/b/c" },
  { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
  { "op": "replace", "path": "/a/b/c", "value": 42 },
  { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
  { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]

在這個JSON Patch的例子中,op代表操作類型,frompath代表目標 json 的層級路徑,value代表操作值。相關語義想必大家都能直接讀出來,更多的信息請參考What is JSON Patch?RFC JSON Patch

示例應用

示常式序引入了swaggerMongoDBdocker-compose等功能,關於 JsonPatch 的部分則使用微軟官方的 JsonPatch 編寫,該庫支持addremovereplacemovecopy方法,實現並不困難。實際使用時,直接以JsonPatchDocument<T>作為包裝即可。

MongoDB 客戶端推薦註冊為單例。

public interface IMongoDatabaseProvider
{
    IMongoDatabase Database { get; }
}

public class MongoDatabaseProvider : IMongoDatabaseProvider
{
    private readonly IOptions<Settings> _settings;

    public MongoDatabaseProvider(IOptions<Settings> settings)
    {
        _settings = settings;
    }

    public IMongoDatabase Database
    {
        get
        {
            var client = new MongoClient(_settings.Value.ConnectionString);
            return client.GetDatabase(_settings.Value.Database);
        }
    }
}

/* Startup/ConfigureServices.cs */
public void ConfigureServices(IServiceCollection services)
{
    …
    services.AddSingleton<IMongoDatabaseProvider, MongoDatabaseProvider>();
    …
}

appsettings.json文件中的資料庫配置部分則為:

{
  "ConnectionString": "mongodb://mongodb",
  "Database": "ExampleDb"
}

docker-compose.yml對 web 應用和 MongoDB 的配置如下:

version: '3.4'

services:
  aspnetcorejsonpatch:
    image: aspnetcorejsonpatch
    build:
      context: .
      dockerfile: AspNetCoreJsonPatch/Dockerfile
    depends_on:
      - mongodb
    ports:
      - "8080:80"
  mongodb:
    image: mongo
    ports:
      - "27017:27017"

啟動時,定位到docker-compose.yml所在文件夾,運行docker-compose up,然後在瀏覽器訪問localhost:8080/swagger,應用在啟動後會自動創建ExampleDb資料庫並插入一條數據。筆者也寫了一個獲取信息的介面/api/Persons,返回值如下:

[
  {
    "name": "LeBron James",
    "oId": "5af995a5b8ea8500018d54b7"
  }
]

然後再使用返回的oId請求/api/Persons/{id}UpdateThenAddThenRemoveAsync)介面,body的 JsonPatch 描述則用:

/* body */
[
  {
    "value": "Daby",
    "path": "FirstName",
    "op": "replace"
  },
  {
    "value": "Example Address",
    "path": "Address",
    "op": "add"
  },
  {
    "path": "Mail",
    "op": "remove"
  }
]

/* PersonsController.cs */
[HttpPatch("{id}")]
public async Task<PersonDto> UpdateThenAddThenRemoveAsync(string id,
    [FromBody] JsonPatchDocument<Person> personPatch)
{
    var objectId = new ObjectId(id);

    var person = await _personRepository.GetAsync(objectId);

    personPatch.ApplyTo(person);

    await _personRepository.UpdateAsync(person);

    return new PersonDto
    {
        OId = person.Id.ToString(),
        Name = $"{person.FirstName} {person.LastName}"
    };
}

其他相關代碼另請查閱。不過需要再提一點的是,Visual Studio 15.7 版本對docker-compose.yml的文本語法解析有些問題,詳見MSBuild failing to parse a valid compose file,比如以下代碼將無法編譯:

environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://0.0.0.0:80
      - ConnectionString=${MONGODB:-mongodb://mongodb}
      - Database=ExampleDb

參考文獻

  1. JSON Patch
  2. Github v3 API

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定位 關於定位 我們可以使用css的position屬性來設置元素的定位類型,postion的設置項如下: relative 生成相對定位元素,元素所占據的文檔流的位置不變,元素本身相對文檔流的位置進行偏移 absolute 生成絕對定位元素,元素脫離文檔流,不占據文檔流的位置,可以理解為漂浮在文檔 ...
  • css元素溢出 當子元素的尺寸超過父元素的尺寸時,需要設置父元素顯示溢出的子元素的方式,設置的方法是通過overflow屬性來設置。 overflow的設置項: 1、visible 預設值。內容不會被修剪,會呈現在元素框之外。2、hidden 內容會被修剪,並且其餘內容是不可見的,此屬性還有清除浮動 ...
  • json數據作為和後臺交互的良好交互方式,這裡介紹下前端怎麼封裝成json數據給到後臺。 示例代碼: (1)封裝成json數據 最終結果為:{"id":0,"name":"張三","job":"學生"} (2)封裝成json數組 最終結果為:[{"id":0,"name":"張三","job":"學 ...
  • 前言 ​最近,被推送了不少秒殺架構的文章,忙裡偷閑自己也總結了一下互聯網平臺秒殺架構設計,當然也借鑒了不少同學的思路。俗話說,脫離案例講架構都是耍流氓,最終使用SpringBoot模擬實現了部分秒殺場景,同時跟大家分享交流一下。 秒殺場景 秒殺場景無非就是多個用戶在同時搶購一件或者多件商品,專用辭彙 ...
  • 上一篇: "ELK 架構之 Elasticsearch 和 Kibana 安裝配置" 閱讀目錄: 1. 環境準備 2. 安裝 Logstash 3. 配置 Logstash 4. Logstash 採集的日誌數據,在 Kibana 中顯示 5. 安裝配置 Filebeat 6. Filebeat 採 ...
  • 單例模式真是一個老掉牙的問題了,不過我今天是要說些裡面更深點的知識,閑話少說,直接來代碼 1、餓漢式 相信這種寫法大家都知道,一開始接觸單例的時候,大家應該都是用的這種方法: 這種方式優點就是線程安全, 缺點也很明顯,就是類載入的時候,就已實例化該對象了,後面有可能用不到這個實例對象,這樣就會造成空 ...
  • 剛畫出來的,MicroService Manager ...
  • 詳情請 咨詢 QQ 759104513 精品新增,持續中.... 192、PHP進階:面向對象及TP5框架初識-慕課網職業路徑 191、0961、手把手帶你入坑H5與小程式直播開發 190、SpringBoot2.0不容錯過的新特性 WebFlux響應式編程 189、Vue2.5開發去哪兒網App ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...