JSON修补程序更新嵌套对象

时间:2020-09-24 14:06:29

标签: c# json asp.net-core json-patch

我一直在尝试使用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}";
    }
}

但是找不到名称

enter image description here

2 个答案:

答案 0 :(得分:1)

找不到约会名称的原因是,在创建Appointment时尚未初始化Contact。将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()替代中,因为它不存在。此外,单/和双//均在路径中起作用。我猜您是在尝试找出问题所在时使用了后者。

现在,由于您已经使用JSON定义了文档,因此无需定义其他替换操作。您的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);

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

答案 1 :(得分:1)

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

public class Contact
{
    public Contact()
    {
        Appointment = new Appointment();
    }

    ...
}

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