PATCH请求REST API之MyDeltas.net

PATCH是REST API支持的请求之一。

REST API的请求常见的是GET和POST,其中PUT、DELETE和PATCH也很重要。

PATCH表示部分更新,用POST当然可以代替,PATCH语义更好更准确。

  1. JSON Patch是一种实现PATCH的方案

  2. ODATA也支持Patch

ODATA包含Delta功能,比JSON Patch简洁

但是Delta只能用于ODataController

  1. MyDeltas.net是本人参考ODATA的Delta功能实现的一个小工具

  2. MyDeltas和JSON Patch对比

|---------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| | |

以上是使用NodeBook实现的对比,大家可以从本项目源码中下载用vscode打开执行测试

gitbub地址: https://github.com/donetsoftwork/MyDelta.net/tree/master/Notes

或gitee地址: https://gitee.com/donetsoftwork/MyDelta.net/tree/master/Notes

以上很明显MyDeltas生成的json比JSON Patch的简洁。

以前很多项目对同一个实体有很多修改方法,改头像、改昵称、改生日、改性别等等,太多了。

用Patch都可以合并,这样就简洁明了。

JSON Patch更适合复杂对象,它支持Add、Remove、Replace等,MyDeltas相当于JSON Patch的Replace

如果我们做微服务的API,实体类简单直接用MyDeltas就好了

这里说的实体类简单并不是说包含的字段少,而是尽量不要一个实体类又包含多个其他实体类的对象

比如Post和Comment,如果Post含Comment列表,用JSON Patch才好处理

如果把Post和Comment拆分两个API,JSON Patch的Add、Remove能用上的机会就不多了

5. MyDeltas功能

5.1 通过nuget安装MyDeltas

复制代码
dotnet add package MyDeltas --version 0.3.0-alpha

5.2 MyDelta通过IMyDeltaFactory工具来构造

复制代码
IMyDeltaFactory factory = new MyDeltaFactory();
MyDelta<TodoItem> delta = factory.Create<TodoItem>();

5.3 MyDelta支持System.Text.Json序列化和反序列化

复制代码
IMyDeltaFactory factory = new MyDeltaFactory();
MyDelta<TodoItem> delta = factory.Create<TodoItem>();
delta.TrySetValue("Name", "Test");
string json = JsonSerializer.Serialize(delta);
//{"Name":"Test"}
复制代码
var json = "{\"Name\":\"Test\"}";
MyDelta<TodoItem>? delta = JsonSerializer.Deserialize<MyDelta<TodoItem>>(json);

其中反序列化也是调用IMyDeltaFactory来构造MyDelta**

5.4 Patch和Put功能都是把MyDelta数据应用到实例对象上**

Patch只应用变更的部分,并返回是否变更成功

Put是把变化部分和没变化部分都复制过去

复制代码
    /// <summary>
    /// 增量修改
    /// </summary>
    /// <param name="original"></param>
    /// <returns>是否变化</returns>
    public bool Patch(TStructuralType original)
    {
        bool changed = false;
        foreach (var item in _data)
        {
            if (_members.TryGetValue(item.Key, out var member))
                changed = member.TrySetValue(original, item.Value);
        }
        return changed;
    }
复制代码
    /// <summary>
    /// 覆盖
    /// </summary>
    /// <param name="original"></param>
    /// <returns></returns>
    public void Put(TStructuralType original)
    {
        foreach (var item in _members)
        {
            if (_data.TryGetValue(item.Key, out var value))
                item.Value.SetValue(original, value);
            else
                item.Value.Copy(_instance, original);
        }
    }

6. MyDeltas性能问题

**MyDelta通过IMyDeltaFactory来操作实体类的属性或字段,默认实现MyDeltaFactory是基于反射的PropertyInfo和FieldInfo

虽然.net9的反射性能已经提高很多了,但与手写代码还是有点差距,为此MyDeltas提供了扩展方案**

6.1 DelegateBuilder手写代码扩展

DelegateBuilder可以直接构造MyDelta也可以扩展IMyDeltaFactory****

复制代码
var builder = new DelegateBuilder<TodoItem>()
    .Add(nameof(TodoItem.Id), obj => obj.Id, (obj, value) => obj.Id = value)
    .Add(nameof(TodoItem.Name), obj => obj.Name, (obj, value) => obj.Name = value)
    .Add(nameof(TodoItem.IsComplete), obj => obj.IsComplete, (obj, value) => obj.IsComplete = value)
    .Add(nameof(TodoItem.Remark), obj => obj.Remark, (obj, value) => obj.Remark = value);
TodoItem todo = new() { Id = 1, Name = "Test1" };
var myDelta = _builder.Create(todo);
myDelta.TrySetValue(nameof(TodoItem.Name), "todo1");

DelegateBuilder没定义的IMyDeltaFactory会补足

复制代码
var builder = new DelegateBuilder<TodoItem>()
    .Add(nameof(TodoItem.Id), obj => obj.Id, (obj, value) => obj.Id = value)
    .Add(nameof(TodoItem.Name), obj => obj.Name, (obj, value) => obj.Name = value);
MyDeltaFactory factory = new MyDeltaFactory()
    .Use(builder.Members);
MyDelta<TodoItem> delta = factory.Create<TodoItem>();

7. 如果嫌弃手写代码太繁琐可以使用MyDeltas.Emit

7.1 通过nuget安装MyDeltas.Emit

复制代码
dotnet add package MyDeltas.Emit --version 0.3.0-alpha

7.2 使用EmitDeltaFactory代替MyDeltaFactory

复制代码
IMyDeltaFactory emitFactory = new EmitDeltaFactory();

7.3 配置Json序列化

复制代码
string json = JsonSerializer.Serialize(delta, new JsonSerializerOptions
{
    Converters =
    {
        new MyDeltaConverterFactory(new MyDeltaFactory())
    }
});
复制代码
    IMyDeltaFactory deltaFactory = new EmitDeltaFactory(emitFactory);
    services.AddSingleton(deltaFactory)
        .AddControllers()
        .AddJsonOptions(options =>
        {
            options.JsonSerializerOptions.Converters.Add(new MyDeltaConverterFactory(deltaFactory));
        });

源码托管地址: https://github.com/donetsoftwork/MyDeltas.net ,也欢迎大家直接查看源码。

gitee同步更新:https://gitee.com/donetsoftwork/MyDeltas.net

文档地址: https://donetsoftwork.github.io/MyDelta.net/index.html

如果大家喜欢请动动您发财的小手手帮忙点一下Star。

相关推荐
Just_Paranoid2 天前
【Gerrit Patch】批量下载 Gerrit 提交的 Patch
git·gerrit·shell·patch
xiangji2 个月前
优雅的.net REST API之FastEndpoints
patch·mydelta
小七de尾巴5 个月前
利用pnpm patch给第三方库打补丁
vue·pnpm·patch·补丁
EleganceJiaBao6 个月前
【嵌入式】嵌入式系统中的 SemVer 版本控制方案
c语言·stm32·嵌入式·patch·semver·major·minor
乐闻x1 年前
如何使用 pnpm 进行打补丁patch操作?推荐两个方法
前端·javascript·pnpm·patch
___波子 Pro Max.1 年前
下载github patch到本地
git·patch
YasinLeeX1 年前
如何向linux社区提交一个新的驱动或patch
linux·ubuntu·驱动·patch·upstream·linux社区·review
dingdingfish2 年前
升级Oracle 单实例数据库19.3到19.22
oracle·database·patch·upgrade·19c
husterlichf2 年前
JSON Merge Patch && JSON PATH
http·json·merge·patch