为何Json.NET尝试反序列化我的仅获取(get-only)属性?
我懂你想要实现的是只序列化特定属性,但反序列化时跳过它的需求,结合你给出的代码片段,我来给你整理完整的可运行方案,分两种场景来说明:
场景1:属性本身是只读计算属性(你的示例情况)
你的Sup类里的yo属性是只读的计算属性(只有get访问器,没有set),Newtonsoft.Json(你代码里的Js...应该是指这个库)默认就会序列化它,但反序列化时不会尝试设置它——因为没有办法给它赋值。完整代码如下:
using Newtonsoft.Json; using System; public interface ISupYo { string Hi { get; } } public class SupYo : ISupYo { public string Hi { get; } = "heya"; } public interface ISup { int hiyo { get; } } public class Sup : ISup { public Sup(int hiyo) { this.hiyo = hiyo; } public int hiyo { get; } // 只读计算属性,默认序列化输出,反序列化忽略 public ISupYo yo => new SupYo(); } class Program { static void Main() { // 序列化 var myNewSup = new Sup(42); var serializedJson = JsonConvert.SerializeObject(myNewSup, Formatting.Indented); Console.WriteLine("序列化结果:"); Console.WriteLine(serializedJson); // 反序列化 var deserializedSup = JsonConvert.DeserializeObject<Sup>(serializedJson, new JsonSerializerSettings { // 允许使用非无参构造函数创建实例 ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor }); Console.WriteLine("\n反序列化后验证:"); Console.WriteLine($"hiyo值:{deserializedSup.hiyo}"); Console.WriteLine($"yo.Hi值:{deserializedSup.yo.Hi}"); // 输出heya,是新生成的实例,而非从JSON读取的 } }
运行后你会看到:序列化的JSON里包含yo字段,但反序列化时,yo属性是重新生成的SupYo实例,不会读取JSON里的对应值。
场景2:属性有setter,但仍要反序列化时忽略
如果以后你给yo属性加了set访问器,但还是想保持「序列化输出,反序列化忽略」的规则,可以用自定义ContractResolver来精确控制:
首先定义解析器:
public class SelectiveSerializeResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); // 指定只对Sup类的yo属性生效:序列化时包含,反序列化时跳过 if (member.DeclaringType == typeof(Sup) && member.Name == nameof(Sup.yo)) { property.Ignored = false; // 确保序列化时不被忽略 property.ShouldDeserialize = _ => false; // 反序列化时直接跳过 } return property; } }
然后使用这个解析器进行序列化和反序列化:
var serializerSettings = new JsonSerializerSettings { ContractResolver = new SelectiveSerializeResolver(), Formatting = Formatting.Indented, ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor }; // 序列化 var serialized = JsonConvert.SerializeObject(myNewSup, serializerSettings); // 反序列化 var deserialized = JsonConvert.DeserializeObject<Sup>(serialized, serializerSettings);
这样不管yo属性有没有setter,都能严格实现「只序列化,不反序列化」的需求。
另外要注意:如果你的Sup类没有无参构造函数,反序列化时需要设置ConstructorHandling.AllowNonPublicDefaultConstructor,或者给类加一个私有的无参构造函数,否则Json.NET无法创建实例。
内容的提问来源于stack exchange,提问作者Gunnar Már Óttarsson
相关产品推荐
相关产品推荐

