json - 在 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> 中添加、删除、替换、复制、移动条目?
解决方案
您使用的格式将设置整个属性值(设置为仅包含一个条目的字典)。这就是为什么您看到它已添加但未更新的原因。
对于通过密钥更新条目,看起来这在任何地方都没有记录。更新密钥(添加或更新现有密钥)的实际语法如下:
/path-to-dictionary/string-key
上面的路径也针对现有条目remove
。
value
then 应该只是输入值(不包括代码中的键),如下所示:
{ "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
推荐阅读
- docker - 运行 Meteor.js。“第一次跑步”是什么意思?
- mysql - 如何在restful api mysql中请求多个字段
- vue.js - vue-cli 如何从组件构建一个库并导入它?
- reactjs - 未经身份验证用户的反应路由器
- java - 使用 Java8 Stream API 合并两个 hashmap 列表
- java - 将指向 ArrayList 的 LinkedList 的指针转换为 String
- .net - 构建 dotnet vuejs 模板时出现“未知浏览器查询”错误
- javascript - 如何在悬停表格行上显示各个表格单元格的内容?
- javascript - 如果变量是数组、字符串、数字,则签入模板
- swift - swift中具有多个参数的函数