JSON 补丁更新嵌套对象

JSON Patch update nested object

我一直在尝试使用 JSON 补丁在嵌套对象中使用替换值,但我觉得我的符号不正确。知道路径应该是什么吗?

我创建了以下代码来证明 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}";
    }
}

但是找不到 名称

找不到约会名称的原因是您在创建 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() 覆盖中,因为它丢失了。此外,单 / 和双 // 都在路径中工作。我猜你在试图找出问题所在时使用了后者。

现在,由于您已经在 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);

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

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

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

    ...
}

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