如何在嵌套JSON文档的数组中添加新对象(C#实现)
问题描述
免责声明:各位,C#并非我的专长;我通常是数据库开发人员。这段代码大多是我从各处拼凑来的,请手下留情。
我想要实现的功能是:打开用户指定的现有JSON文档,添加一个新对象到其中,然后将更新后的内容保存回文件。以下是一个符合实际结构的示例JSON,我需要为其中的"person"添加新的"car",新的车辆信息来自文本框和下拉框。
{"Name": "Bob Bob","City": "Louisville","State": "Kentucky","Address": "123 City Ln","Cars": [{"Make": "Ford","Model": "Explorer","Color": "White"},{"Make": "Dodge","Model": "Caravan","Color": "White"},{"Make": "Bat","Model": "Mobile","Color": "Black:"}],"Jobs": [{"Employer": "Walmart","Position": "Greeter","Pay": "$35,000","EndDate": "12/25/1999"},{"Employer": "Target","Position": "Cashier","Pay": "$32,000","EndDate": "1/1/2002"},{"Employer": "SkyNet","Position": "Programmer","Pay": "$86,000","EndDate": "5/8/2023"}]}
我已定义以下实体类:
public class Person { public string Name { get; set;} public string City { get; set;} public string State { get; set;} public string Address { get; set;} public Cars[] Cars {get; set;} public Jobs[] Jobs {get; set;} } public class Cars { public string Make { get; set;} public string Model { get; set;} public string Color { get; set;} } public class Jobs { public string Employer { get; set;} public string Position { get; set;} public string Pay { get; set;} public string EndDate { get; set;} }
我的现有代码如下:
private void btnSaveUpdates_Click(object sender, EventArgs e) { string Make = cbMake.Text; string Model = txtModel.Text; string Color = cbColor.Text; string filePath = txtFileLoc.Text; DoJSONWork(filePath, Make, Model, Color); } public static void DoJSONWork(string filePath, string Make, string Model, string Color) { var FileStream = File.OpenRead(filePath); using (StreamReader reader = new StreamReader(FileStream)) { using (JsonTextReader JSONreader = new JsonTextReader(reader)) { JSONreader.SupportMultipleContent = true; var serializer = new JsonSerializer(); while (JSONreader.Read()) { if (JSONreader.TokenType == JsonToken.StartObject) { Person p = serializer.Deserialize<Person>(JSONreader); Cars cars = p.Cars.FirstOrDefault(c => c.Make + c.Model + c.Color == Make + Model + Color); if (cars == null) { cars = new Cars { Make = Make, Model = Model, Color = Color }; p.Cars = p.Cars.Concat(new Cars[] { cars }).ToArray(); } } } } } //I honestly don't know what to do next }
我正困惑于如何更新JSON文档中的"cars"数组,是否需要对整个JSON文档进行反序列化和序列化操作?
解决方案
没错,必须先把整个JSON文件反序列化成Person对象,修改完Cars数组后,再把整个对象序列化回文件。你的现有代码已经完成了反序列化和对象修改的步骤,缺的就是把修改后的对象写回文件的部分。
下面是调整后的完整代码,同时优化了几个细节:
private void btnSaveUpdates_Click(object sender, EventArgs e) { string make = cbMake.Text.Trim(); string model = txtModel.Text.Trim(); string color = cbColor.Text.Trim(); string filePath = txtFileLoc.Text.Trim(); // 先校验输入有效性 if (string.IsNullOrEmpty(make) || string.IsNullOrEmpty(model) || string.IsNullOrEmpty(color) || !File.Exists(filePath)) { MessageBox.Show("请填写完整车辆信息,或确认文件路径有效"); return; } UpdateCarInJson(filePath, make, model, color); } public static void UpdateCarInJson(string filePath, string make, string model, string color) { try { // 1. 读取文件内容并反序列化为Person对象 string jsonContent = File.ReadAllText(filePath); Person person = JsonConvert.DeserializeObject<Person>(jsonContent); // 2. 检查是否已存在相同车辆(改进判断逻辑,避免字符串拼接的潜在问题) bool carExists = person.Cars.Any(c => string.Equals(c.Make, make, StringComparison.OrdinalIgnoreCase) && string.Equals(c.Model, model, StringComparison.OrdinalIgnoreCase) && string.Equals(c.Color, color, StringComparison.OrdinalIgnoreCase)); if (!carExists) { // 创建新车辆并加入数组 var newCar = new Cars { Make = make, Model = model, Color = color }; // 用List处理添加操作更高效,再转回数组 var carList = person.Cars.ToList(); carList.Add(newCar); person.Cars = carList.ToArray(); } // 3. 序列化修改后的对象并写入文件 string updatedJson = JsonConvert.SerializeObject(person, Formatting.Indented); File.WriteAllText(filePath, updatedJson); MessageBox.Show("车辆信息更新成功"); } catch (Exception ex) { MessageBox.Show($"操作失败:{ex.Message}"); } }
关键细节说明:
- 用
File.ReadAllText和File.WriteAllText简化文件操作,无需手动处理Stream和读写器 - 判断重复车辆时,用
StringComparison.OrdinalIgnoreCase忽略大小写(若需严格区分,可去掉该参数) Formatting.Indented让生成的JSON带缩进,方便人工查看,不需要的话换成Formatting.None即可- 用
List<T>.Add替代Concat,数组元素较多时性能更优
内容的提问来源于stack exchange,提问作者user1603398
相关产品推荐
相关产品推荐

