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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...