使用 Http Patch 上的对象列表的最佳方法

Posted

技术标签:

【中文标题】使用 Http Patch 上的对象列表的最佳方法【英文标题】:Best way to work with list of objects on Http Patch 【发布时间】:2020-10-21 07:46:08 【问题描述】:

在我的场景中,我有一个 Web 客户端,并且 Web 客户端中的 rest api (.NET Core) 有一个列出所有客户端的页面,在此列表中,用户可以选择许多客户端并将它们标记为已启用。 如何在我的 api 中处理“标记为启用”? 我可以在方法 PATCH 上一一更新,但对于列表我不知道如何。

public IActionResult Patch( long id, [FromBody] JsonPatchDocument<Client> patch )

    var client = base.DataContext.Clients.Find( id );

    if( client != null )
        patch.ApplyTo( client, ModelState );

    return Ok();


public class Client

    public string Name  get; set; 

    public string Description  get; set; 

    public bool Enabled  get; set; 

【问题讨论】:

嗨 Luis,你会在这里找到很多帮助,但现在你的问题太笼统了,首先你需要展示你已经尝试过的内容,你遇到的具体问题是什么,你一直无法找到答案 【参考方案1】:

修补List的HttpPatch动作与Object相同。

        [HttpPatch]
        public IActionResult JsonPatchForClients([FromBody] JsonPatchDocument<List<Client>> patchDoc)
        
            var clients = CreateClients();

            patchDoc.ApplyTo(clients);

            return new ObjectResult(clients);
        

        private List<Client> CreateClients()
        
            return  new List<Client>()
            
                    new Client
                    
                        Name = "Client0",
                        Description = "Description0",
                        Enabled = true
                    ,
                    new Client
                    
                        Name = "Client1",
                        Description = "Description1",
                        Enabled = true
                    ,
                    new Client
                    
                        Name = "Client2",
                        Description = "Description2",
                        Enabled = true
                    
            ;
        

        public class Client
        
            public string Name  get; set; 

            public string Description  get; set; 

            public bool Enabled  get; set; 
        

接下来,我将详细介绍如何发送Patch Body。

这是原始列​​表:

[
    
        "name": "Client0",
        "description": "Description0",
        "enabled": true
    ,
    
        "name": "Client1",
        "description": "Description1",
        "enabled": true
    ,
    
        "name": "Client2",
        "description": "Description2",
        "enabled": true
    
]

1.添加到“/-”数组的末尾,并添加到“/0”数组的第一个

    [
      
        "op": "add",
        "path": "/-",
        "value": 
          "name": "Order3",
          "description": "Description3",
          "enabled": true
        
      
    ]

结果:

[
    
        "name": "Client0",
        "description": "Description0",
        "enabled": true
    ,
    
        "name": "Client1",
        "description": "Description1",
        "enabled": true
    ,
    
        "name": "Client2",
        "description": "Description2",
        "enabled": true
    ,
    
        "name": "Order3",
        "description": "Description3",
        "enabled": true
    
]

2。替换 Order3Order0

[
  
    "op": "replace",
    "path": "/0",
    "value": 
      "name": "Order3",
      "description": "Description3",
      "enabled": true
    
  
]

结果:

[
    
        "name": "Order3",
        "description": "Description3",
        "enabled": true
    ,
    
        "name": "Client1",
        "description": "Description1",
        "enabled": true
    ,
    
        "name": "Client2",
        "description": "Description2",
        "enabled": true
    
]

3.Remve Client0

[
  
    "op": "remove",
    "path": "/0"
  
]

结果:

[
    
        "name": "Client1",
        "description": "Description1",
        "enabled": true
    ,
    
        "name": "Client2",
        "description": "Description2",
        "enabled": true
    
]
    其他(move,copy,test)你可以在microsoft doc找到。

【讨论】:

但这是数组“path”的顺序:“/0”,如果顺序改变我会更新一个错误的项目。我的页面必须知道我的列表的 a 项目位置,但是这个列表来自 DB,并且会被排序、过滤等等。 无法通过某些属性从数组中选择元素。对于更新对象列表,您应该考虑放弃 JsonPatch。 JSONPatch 旨在以非常明确的方式更新 API 上的文档。【参考方案2】:

另一种方式是replaceall。

    [HttpPatch]
    public IActionResult JsonPatchForClients([FromBody] JsonPatchDocument  patchDoc)
    
        var clients = new Clients();
        patchDoc.ApplyTo(clients);

        return new ObjectResult(clients);
    

    public class Clients
    
        public List<Client> clients  get; set; 
        public Clients()
        
           clients = new List<Client>()
            
                new Client
                
                    Name = "Client0",
                    Description = "Description0",
                    Enabled = true
                ,
                new Client
                
                    Name = "Client1",
                    Description = "Description1",
                    Enabled = true
                ,
                new Client
                
                    Name = "Client2",
                    Description = "Description2",
                    Enabled = true
                
        ;
    
    

JSONPatch 的主体:

 [
      
        "op": "replace",
        "path": "/clients",
        "value": [
          
          "name": "clients1",
          "description": "Desc1",
          "enabled": false
        ,
          "name": "clients2",
          "description": "Desc2",
          "enabled": false
        
        ]
      
    ]

这样,我们可以更新列表的每个对象。但这与正常方式非常相似(将模型传递给行动)。

【讨论】:

嗨 Luis,你试过全部替换吗?同时,我认为 HTTP PATCH 不是在您的情况下更新列表对象的好方法。 HTTP PUT vs HTTP PATCH 从这里看到baeldung.com/http-put-patch-difference-spring 如果坚持使用HTTP PATCH,请逐个尝试补丁,但不要列出。

以上是关于使用 Http Patch 上的对象列表的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

创建完整的只读对象列表的最佳方法

连接字符串对象列表的最佳方法? [复制]

批处理位于 Google Cloud Storage Bucket 上的对象的最佳方法

使列表中的子对象自我转换为同一父对象的其他子对象的最佳方法

Ruby中使用patch HTTP方法

无效的 HTTP 方法:PATCH > 正在执行 PATCH :引起:feign.RetryableException: