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。

相关推荐
小七de尾巴3 个月前
利用pnpm patch给第三方库打补丁
vue·pnpm·patch·补丁
EleganceJiaBao4 个月前
【嵌入式】嵌入式系统中的 SemVer 版本控制方案
c语言·stm32·嵌入式·patch·semver·major·minor
乐闻x9 个月前
如何使用 pnpm 进行打补丁patch操作?推荐两个方法
前端·javascript·pnpm·patch
___波子 Pro Max.10 个月前
下载github patch到本地
git·patch
YasinLeeX1 年前
如何向linux社区提交一个新的驱动或patch
linux·ubuntu·驱动·patch·upstream·linux社区·review
dingdingfish1 年前
升级Oracle 单实例数据库19.3到19.22
oracle·database·patch·upgrade·19c
husterlichf2 年前
JSON Merge Patch && JSON PATH
http·json·merge·patch
woloqun2 年前
Spark低版本适配Celeborn
spark·编译·patch·celeborn·动态资源
smallerxuan2 年前
如何用BCompare打增量包
1024程序员节·bcompare·打版本增量包·patch