首页 > 解决方案 > 在 ASP.NET Core 中使用 JsonPatch 将项目添加到字典

问题描述

我有以下环境和版本的.NET Core

.NET SDK (reflecting any global.json):
 Version:   5.0.100
 Commit:    5044b93829

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  11.0
 OS Platform: Darwin
 RID:         osx.11.0-x64
 Base Path:   /usr/local/share/dotnet/sdk/5.0.100/

使用以下代码和端点。

public class Trie
{
    public string Id { get; set; }

    public Dictionary<string, TrieNode> Nodes { get; set; }
}

public class TrieNode
{
    public string Name { get; set; }
}
public async Task<IActionResult> Patch(string id, [FromBody] JsonPatchDocument<Trie> patchDoc)
{
    var trie = [get from database]
    patchDoc.ApplyTo(trie, ModelState);
}

当我使用以下操作时:

[
  {
    "op": "add",
    "path": "/nodes/-", "value": { "/": { "name": "hello, world" } }
  }
]

一个项目被添加到字典中,如下所示:

"Nodes": {
    "-": {
        "Name": null
    }
}

如果我对 op 使用以下语法

[
  {
    "op": "add",
    "path": "/nodes", "value": { "/": { "name": "hello, world" } }
  }
]

该项目是这样添加的:

"Nodes": {
    "/": {
        "Name": "hello, world"
    }
}

但是当我尝试使用另一个这样的键添加新项目时:

[
  {
    "op": "add",
    "path": "/nodes", "value": { "/my-key": { "name": "hello, world" } }
  }
]

该项目添加,它替换了第一个条目,因此结果如下所示:

"Nodes": {
    "/my-key": {
        "Name": "hello, world"
    }
}

如何在 Dictionary<string, TrieNode> 中添加、删除、替换、复制、移动条目?

标签: jsonasp.net-core.net-corejson-patch

解决方案


您使用的格式将设置整个属性值(设置为仅包含一个条目的字典)。这就是为什么您看到它已添加但未更新的原因。

对于通过密钥更新条目,看起来这在任何地方都没有记录。更新密钥(添加或更新现有密钥)的实际语法如下:

/path-to-dictionary/string-key

上面的路径也针对现有条目remove

valuethen 应该只是输入值(不包括代码中的键),如下所示:

{ "name": "hello, world" }

以下是不同操作的示例格式:

添加或更新

[
  {
    "op": "add",
    "path": "/nodes/my-key", 
    "value": { "name": "hello, world" }
  }
]

删除

[
  {
    "op": "remove",
    "path": "/nodes/my-key"
  }
]

替换:这实际上类似于add现有密钥。

[
  {
    "op": "replace",
    "path": "/nodes/my-key",
    "value": { "name": "hello, world" }
  }
]

复制

[
  {
    "op": "copy",
    "from": "/nodes/my-existing-key",
    "path": "/nodes/my-key"
  }
]

移动

[
  {
    "op": "move",
    "from": "/nodes/my-existing-key",
    "path": "/nodes/my-key"
  }
]

注意:字典的路径格式要求字典属性为非空。否则,该路径将被视为不存在,并会引发错误,并带有如下消息:

... 找不到路径“/nodes/my-key”指定的目标位置

使用代码中使用的格式,将设置整个字典属性。这就是为什么总是留下一个条目(最后一个会覆盖所有其他条目,包括现有条目)。有了这个注释,您应该确保首先初始化您的字典属性,如下所示:

if(trie.Nodes == null){
   trie.Nodes = new Dictionary<string, TrieNode>();
}
patchDoc.ApplyTo(trie, ModelState);

关于字典键类型

在您的示例中,键类型是string,但它可以是任何类型,只要您有一个关联TypeConverter以使该类型正常工作。例如:可以int这样您就可以正常使用 int 键,也可以这样您可以使用诸如(在路径中使用)之类的DateTime键格式...yyyy-MM-dd


推荐阅读