JSON补丁更新嵌套对象

Posted

技术标签:

【中文标题】JSON补丁更新嵌套对象【英文标题】:JSON Patch update nested object 【发布时间】:2021-01-10 20:26:41 【问题描述】:

我一直在尝试使用 JSON Patch 在嵌套对象中使用替换值,但是我觉得我没有得到正确的表示法。任何想法应该是什么路径?

我在LINQPad 6 中创建了以下代码来证明它。

void Main()

    var patchTest = new PatchTest();
    patchTest.Create();
    patchTest.ToString().Dump("Before Patch");
    var patch = JsonConvert.DeserializeObject<JsonPatchDocument<Contact>>(
        @"[
    
      ""op"": ""replace"",
      ""path"": ""/firstname"",
      ""value"": ""Benjamin""
    ,
    
      ""op"": ""replace"",
      ""path"": ""age"",
      ""value"": ""29""
    ,
    
      ""op"": ""replace"",
      ""path"": ""//Appointment//Name"",
      ""value"": ""fsdfdsf""
    ,
]");
    patchTest.Patch(patch);
    patchTest.ToString().Dump("After Patch");


public class PatchTest

    public Contact Contact  get; set; 

    public PatchTest()  

    public void Create()
    
        Contact = new Contact
        
            FirstName = "Walt",
            LastName = "Banks",
            Age = 20
        ;
    

    public void Patch(JsonPatchDocument<Contact> patch)
    
        patch.Replace(e => e.Appointment, Contact.Appointment);
        patch.ApplyTo(Contact);
    

    public override string ToString()
    
        return $"nameof(Contact): Contact";
    


public class Contact

    public string FirstName  get; set; 
    public string LastName  get; set; 
    public int Age  get; set; 
    public Appointment Appointment  get; set; 

    public override string ToString()
    
        return $"nameof(FirstName): FirstName, nameof(LastName): LastName, nameof(Appointment): Appointment";
    



public class Appointment

    public string Name  get; set; 

    public override string ToString()
    
        return $"nameof(Name): Name";
    

但是找不到名字

【问题讨论】:

【参考方案1】:

找不到约会名称的原因是因为您在创建Contact 时没有初始化Appointment。将Create 更改为:

public void Create()

    Contact = new Contact
    
        FirstName = "Walt",
        LastName = "Banks",
        Age = 20,
        Appointment = new Appointment()
    ;

现在在控制台应用程序中运行您的示例会产生以下输出:

Before Patch
Contact: FirstName: Walt, LastName: Banks, Age: 20, Appointment: Name:
After Patch
Contact: FirstName: Benjamin, LastName: Banks, Age: 29, Appointment: Name: fsdfdsf

我将Contact.Age 添加到其ToString() 覆盖中,因为它丢失了。此外,单 / 和双 // 都在路径中工作。我猜你在试图找出问题所在时使用了后者。

现在,由于您已经在 J​​SON 中定义了文档,因此您不需要定义另一个替换操作。您的Patch 方法可以简化为:

public void Patch(JsonPatchDocument<Contact> patch)

    patch.ApplyTo(Contact);

并且输出将与以前相同。相当于在代码中完成所有这些操作,而无需手动创建 JSON 文档,如下所示:

public void Patch(Contact amendedContact)

    var patch = new JsonPatchDocument<Contact>();
    patch.Replace(e => e.FirstName, amendedContact.FirstName);
    patch.Replace(e => e.Age, amendedContact.Age);
    patch.Replace(e => e.Appointment.Name, amendedContact.Appointment.Name);
    patch.ApplyTo(Contact);

这样称呼它:

var amendedContact = new Contact

    FirstName = "Benjamin",
    Age = 29,
    Appointment = new Appointment
    
        Name = "fsdfdsf"
    
;

patchTest.Patch(amendedContact);

这又会产生您想要的输出。但是您仍然必须确保初始化嵌套属性,否则您将遇到原始问题。

【讨论】:

【参考方案2】:

您正在尝试为未初始化的Appointment 上的Name 属性设置值。创建新实例时更新Contact类以初始化属性:

public class Contact

    public Contact()
    
        Appointment = new Appointment();
    

    ...

根据经验,您应该尝试初始化所有类似的属性,以确保其他类不会发生类似的问题。

【讨论】:

以上是关于JSON补丁更新嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 json 补丁更新集合

在 ASP.NET Core WebAPI 中实现 JSON 合并补丁

怎样更新windows安全补丁

WSUS离线补丁更新

Windows 7 update 補丁查更新历史记录成功,但查看已安装的更新未发现补丁

win7系统卸载补丁包更新的解决方法