找回密码
 立即注册
首页 业界区 业界 PATCH请求REST API之MyDeltas.net

PATCH请求REST API之MyDeltas.net

懵崭 昨天 23:16
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
3. MyDeltas.net是本人参考ODATA的Delta功能实现的一个小工具
4. MyDeltas和JSON Patch对比
1.png

 
 
2.png

 
以上是使用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
  1. dotnet add package MyDeltas --version 0.3.0-alpha
复制代码
5.2 MyDelta通过IMyDeltaFactory工具来构造
  1. IMyDeltaFactory factory = new MyDeltaFactory();
  2. MyDelta<TodoItem> delta = factory.Create<TodoItem>();
复制代码
5.3 MyDelta支持System.Text.Json序列化和反序列化
  1. IMyDeltaFactory factory = new MyDeltaFactory();
  2. MyDelta<TodoItem> delta = factory.Create<TodoItem>();delta.TrySetValue("Name", "Test");string json = JsonSerializer.Serialize(delta);//{"Name":"Test"}
复制代码
  1. var json = "{"Name":"Test"}";
  2. MyDelta<TodoItem>? delta = JsonSerializer.Deserialize<MyDelta<TodoItem>>(json);
复制代码
其中反序列化也是调用IMyDeltaFactory来构造MyDelta
5.4 Patch和Put功能都是把MyDelta数据应用到实例对象上
Patch只应用变更的部分,并返回是否变更成功
Put是把变化部分和没变化部分都复制过去
  1.     /// <summary>
  2.     /// 增量修改
  3.     /// </summary>
  4.     /// <param name="original"></param>
  5.     /// <returns>是否变化</returns>
  6.     public bool Patch(TStructuralType original)
  7.     {
  8.         bool changed = false;
  9.         foreach (var item in _data)
  10.         {
  11.             if (_members.TryGetValue(item.Key, out var member))
  12.                 changed = member.TrySetValue(original, item.Value);
  13.         }
  14.         return changed;
  15.     }
复制代码
  1.     /// <summary>
  2.     /// 覆盖
  3.     /// </summary>
  4.     /// <param name="original"></param>
  5.     /// <returns></returns>
  6.     public void Put(TStructuralType original)
  7.     {
  8.         foreach (var item in _members)
  9.         {
  10.             if (_data.TryGetValue(item.Key, out var value))
  11.                 item.Value.SetValue(original, value);
  12.             else
  13.                 item.Value.Copy(_instance, original);
  14.         }
  15.     }
复制代码
6. MyDeltas性能问题
MyDelta通过IMyDeltaFactory来操作实体类的属性或字段,默认实现MyDeltaFactory是基于反射的PropertyInfo和FieldInfo
虽然.net9的反射性能已经提高很多了,但与手写代码还是有点差距,为此MyDeltas提供了扩展方案
6.1 DelegateBuilder手写代码扩展
DelegateBuilder可以直接构造MyDelta也可以扩展IMyDeltaFactory
  1. var builder = new DelegateBuilder<TodoItem>()
  2.     .Add(nameof(TodoItem.Id), obj => obj.Id, (obj, value) => obj.Id = value)
  3.     .Add(nameof(TodoItem.Name), obj => obj.Name, (obj, value) => obj.Name = value)
  4.     .Add(nameof(TodoItem.IsComplete), obj => obj.IsComplete, (obj, value) => obj.IsComplete = value)
  5.     .Add(nameof(TodoItem.Remark), obj => obj.Remark, (obj, value) => obj.Remark = value);
  6. TodoItem todo = new() { Id = 1, Name = "Test1" };
  7. var myDelta = _builder.Create(todo);
  8. myDelta.TrySetValue(nameof(TodoItem.Name), "todo1");
复制代码
DelegateBuilder没定义的IMyDeltaFactory会补足
  1. var builder = new DelegateBuilder<TodoItem>()
  2.     .Add(nameof(TodoItem.Id), obj => obj.Id, (obj, value) => obj.Id = value)
  3.     .Add(nameof(TodoItem.Name), obj => obj.Name, (obj, value) => obj.Name = value);
  4. MyDeltaFactory factory = new MyDeltaFactory()
  5.     .Use(builder.Members);
  6. MyDelta<TodoItem> delta = factory.Create<TodoItem>();
复制代码
 
7. 如果嫌弃手写代码太繁琐可以使用MyDeltas.Emit
 7.1 通过nuget安装MyDeltas.Emit
  1. dotnet add package MyDeltas.Emit --version 0.3.0-alpha
复制代码
7.2 使用EmitDeltaFactory代替MyDeltaFactory
  1. IMyDeltaFactory emitFactory = new EmitDeltaFactory();
复制代码
7.3 配置Json序列化
  1. string json = JsonSerializer.Serialize(delta, new JsonSerializerOptions
  2. {
  3.     Converters =
  4.     {
  5.         new MyDeltaConverterFactory(new MyDeltaFactory())
  6.     }
  7. });
复制代码
  1.     IMyDeltaFactory deltaFactory = new EmitDeltaFactory(emitFactory);
  2.     services.AddSingleton(deltaFactory)
  3.         .AddControllers()
  4.         .AddJsonOptions(options =>
  5.         {
  6.             options.JsonSerializerOptions.Converters.Add(new MyDeltaConverterFactory(deltaFactory));
  7.         });
复制代码
 
 
源码托管地址: https://github.com/donetsoftwork/MyDeltas.net ,也欢迎大家直接查看源码。
gitee同步更新:https://gitee.com/donetsoftwork/MyDeltas.net
文档地址: https://donetsoftwork.github.io/MyDelta.net/index.html
如果大家喜欢请动动您发财的小手手帮忙点一下Star。
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册