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 不会发生类似的问题。
我一直在尝试使用 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 不会发生类似的问题。