如何让Newtonsoft序列化字段但反序列化时忽略该字段
以下C#代码使用Newtonsoft.Json进行序列化和反序列化时出现异常:序列化后的JSON中Chickens集合仅有1个元素,但反序列化后TopPork.Chickens的元素数量变为2个。问题源于只读属性TopPork在反序列化过程中被错误处理,但直接添加[JsonIgnore]会导致该属性在序列化时也被排除,不符合需求。
代码示例:
public static void Main() { var beef = new Beef() { Porks = [ new() { Index = 1, Chickens = [new() { Hello = "World" } ] } ] }; var beefAsJson = JsonConvert.SerializeObject(beef); Console.WriteLine(beefAsJson); var beef2 = JsonConvert.DeserializeObject<Beef>(beefAsJson); Console.WriteLine(beef2.TopPork.Chickens.Count()); } public class Beef { public List<Pork> Porks { get; set; } public Pork TopPork => Porks.OrderByDescending(i => i.Index).FirstOrDefault(); } public class Pork { public int Index { get; set; } public List<Chicken> Chickens { get; set; } = []; } public class Chicken { public string Hello { get; set; } }
反序列化时,Newtonsoft.Json会尝试解析JSON中的所有属性(包括只读属性TopPork)。虽然TopPork是计算属性,序列化时会被默认包含到JSON中;但反序列化时,解析器会在赋值Porks后尝试处理TopPork,触发Porks.OrderByDescending(...)的逻辑。此时Pork对象的Chickens集合已经被反序列化填充了元素,加上类中默认初始化的空列表,最终导致集合元素被重复添加,数量翻倍。
要实现序列化时保留TopPork,反序列化时忽略它,可以使用以下两种方法:
方法1:使用JsonProperty标记只读属性
给TopPork添加[JsonProperty(ReadOnly = true)]属性,明确告知序列化器:该属性仅参与序列化,反序列化时忽略它。
修改后的Beef类:
public class Beef { public List<Pork> Porks { get; set; } [JsonProperty(ReadOnly = true)] public Pork TopPork => Porks.OrderByDescending(i => i.Index).FirstOrDefault(); }
方法2:私有属性代理序列化(兼容低版本Newtonsoft)
如果你的Newtonsoft.Json版本不支持JsonProperty.ReadOnly参数,可以通过私有属性代理TopPork的序列化逻辑,原属性添加[JsonIgnore]避免反序列化处理:
修改后的Beef类:
public class Beef { public List<Pork> Porks { get; set; } [JsonIgnore] public Pork TopPork => Porks.OrderByDescending(i => i.Index).FirstOrDefault(); [JsonProperty("TopPork")] private Pork SerializeTopPork => TopPork; }
修改后重新运行代码,序列化后的JSON依然包含TopPork字段,反序列化后beef2.TopPork.Chickens.Count()输出为1,符合预期。
内容的提问来源于stack exchange,提问作者zXynK

