为何JsonConvert.DeserializeObject无法设置私有属性,但PopulateObject可以?
Json.Net中PopulateObject可直接设置私有setter属性的原因
现象说明
使用Json.Net时,常规的JsonConvert.DeserializeObject反序列化私有setter属性,必须给属性添加[JsonProperty]特性才能生效;但使用JsonConvert.PopulateObject填充已实例化的对象时,即便私有setter属性没加[JsonProperty],也能成功赋值。
示例代码
定义待处理类
public class Class_A { [JsonProperty] Class_B m_subData = new Class_B("Default data"); } public class Class_B{ public string Data {get;private set;} public Class_B(string data){ Data = data; } }
两种反序列化方式的差异
- 用
DeserializeObject时,Class_B的Data属性会保留默认值,必须给Data加[JsonProperty]才能正常赋值。 - 用
PopulateObject时,无需修改Class_B的代码就能成功填充:
public class DataManager{ public void DeserializeData(string jsonData){ var classAObj = (Class_A) Activator.CreateInstance(typeof(Class_A)); var settings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }; JsonConvert.PopulateObject(jsonData, classAObj, settings); } }
核心原因
两者的底层处理逻辑完全不同:
DeserializeObject是从无到有创建对象,它会严格遵循Json.Net的序列化规则:默认只识别公共成员,私有setter属性不属于默认序列化范围,必须通过[JsonProperty]明确标记为可序列化成员,才会调用setter赋值。PopulateObject是对已存在的对象进行属性填充,它直接通过.NET的反射机制,绕过访问修饰符的限制,直接修改属性对应的私有后备字段(比如自动属性编译后生成的<Data>k__BackingField)。它不需要调用属性的setter方法,也不需要依赖构造函数,自然不需要[JsonProperty]来授权访问。
简单说:PopulateObject不跟setter打交道,直接改底层字段,所以私有setter的限制对它无效。
内容的提问来源于stack exchange,提问作者alaslipknot
相关产品推荐
相关产品推荐

