簡體   English   中英

在 ASP.NET Core WebAPI 中實現 JSON Merge Patch

[英]Implementing JSON Merge Patch in ASP.NET Core WebAPI

我有興趣在我的 ASP.NET Core WebAPI 中添加對部分更新的支持,我只更新調用者提供的資源上的屬性,而排除的屬性保持不變。

對於上下文,假設我有一個可以描述如下的資源:

GET /users/1
{
    title: "Mister",
    firstName: "Frederick",
    middleName: "McFeely",
    lastName: "Rodgers"
}

如果我想允許消費者將存儲在firstName屬性中的值從“Frederick”單獨更改為“Fred”,我應該能夠公開一個支持JSON Merge Patch Content-TypePATCH端點,如下所示:

PATCH /users/1
Content-Type: application/merge-patch+json
{
    firstName: "Fred"
}

但是,我認為沒有簡單的方法可以知道firstName是唯一正在更新的屬性。 例如,如果我要制作一個接受PATCH動詞的控制器,它可以像這樣搭建:

[Route("users")]
public class UsersController : Controller {

    [HttpPatch("{userId:int}")]
    public User Patch([FromRoute] int userId, [FromBody] User user) {

        // How do I know which properties were set on User at this point?

    }

}

public class User {

    public String Title { get; set; }
    public String FirstName { get; set; }
    public String MiddleName { get; set; }
    public String LastName { get; set; }

}

但是我不知道如何在 JSON 對象作為User水合並傳遞給我的控制器之前提取在 JSON 對象上定義了哪些屬性的鍵。 我不能假設null值意味着一個屬性被排除在外,因為調用者可以將一個可選屬性顯式設置為 null。

編輯

我知道Microsoft.AspNetCore.JsonPatch庫。 不幸的是,這期望調用者使用“[更改說明]”來定義一個PATCH ,如RFC 5789 中所述,我發現它不直觀且冗長。 我指的是RFC 7396 中定義的“JSON Merge Patch”。

我找到了一個有效的庫: https : //github.com/Morcatko/Morcatko.AspNetCore.JsonMergePatch

[HttpPatch]
[Consumes(JsonMergePatchDocument.ContentType)]
public void Patch([FromBody] JsonMergePatchDocument<Model> patch)
{
    ...
    patch.ApplyTo(backendModel);
    ...
}

或者使用patch.JsonPatchDocument.Operations手動遍歷補丁請求字段。

看起來,對於合並補丁,您將不得不等待 odata 支持。

它目前處於測試階段,並支持與 Delta<> 類的合並語義。

https://www.nuget.org/packages/Microsoft.AspNetCore.OData/

對於簡單類型,我使用Newtonsoft.Json 合並JObjects 找到了一個非常簡單的解決方案:

public static T Patched<T>(T source, JObject patch) where T : class
{
    var sourceObject = JObject.FromObject(source);
    sourceObject.Merge(patch, new JsonMergeSettings() {MergeArrayHandling = MergeArrayHandling.Union});
    return sourceObject.ToObject<T>();
}

public static T Patched<T>(T source, string patchCode) where T : class
{
    return Patched<T>(source, JObject.Parse(patchCode));
}

希望這可以幫助搜索此主題並尋找沒有外部軟件包的簡單解決方案的人。

要打補丁,您必須定義 PatchDocument。

更多關於它你可以找到PatchDocument

方法示例。

 [HttpPatch("{userId:int}")]   
 public IActionResult UserPatch(int userId, [FromBody] JsonPatchDocument<User> patchDocument) {

    var user = new User();
    // Because it comes from url.
    user.Id = userId;
    patchDocument.ApplyTo(user);

    // Here you call context or repository to save.

  }

文檔示例。

[
  { "op": "replace", "path": "/firstName", "value": "boo" },
]

這會將用戶模型中的 firstName 字段更新為“boo”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM