如何让Newtonsoft.Json反序列化时创建Result新实例而非修改静态只读对象?
解决枚举类模式下Json反序列化修改静态实例的问题
问题描述
我定义了继承自TypesafeEnumBase的Result类,并用枚举类模式创建了静态只读实例Result.NotStarted。IOResultBase类的构造函数默认将Result属性赋值为Result.NotStarted。但使用JsonConvert.DeserializeObject反序列化JSON字符串{"Result":{"text":"","code":0,"name":"Success"}}得到IOResultBase对象时,发现静态只读的Result.NotStarted的Id被修改为0,而不是为foo.Result创建新的实例。请问如何强制反序列化时创建Result新实例?
解决方案
1. 为Result类编写自定义Json转换器
创建一个继承自JsonConverter<Result>的转换器,在反序列化时直接实例化新的Result对象,避免复用已有静态实例:
public class ResultConverter : JsonConverter<Result> { public override Result ReadJson(JsonReader reader, Type objectType, Result existingValue, bool hasExistingValue, JsonSerializer serializer) { // 加载JSON对象并读取属性值 var jObject = JObject.Load(reader); var text = jObject["text"].ToString(); var code = jObject["code"].Value<int>(); var name = jObject["name"].ToString(); // 直接创建新的Result实例返回 return new Result(code, name, text); // 注意:需确保Result类提供了对应参数的构造函数 } public override void WriteJson(JsonWriter writer, Result value, JsonSerializer serializer) { // 序列化逻辑保持默认实现即可,可根据需求调整 serializer.Serialize(writer, value); } }
2. 注册自定义转换器
有两种方式让Json.NET使用这个转换器:
- 特性标记:在
Result类上添加特性,指定转换器:[JsonConverter(typeof(ResultConverter))] public class Result : TypesafeEnumBase { // 类的原有实现... public static readonly Result NotStarted = new Result(1, "NotStarted", "未开始"); } - 全局配置:在反序列化时传入包含转换器的设置,对所有反序列化操作生效:
var jsonString = "{\"Result\":{\"text\":\"\",\"code\":0,\"name\":\"Success\"}}"; var settings = new JsonSerializerSettings(); settings.Converters.Add(new ResultConverter()); var iOResultBase = JsonConvert.DeserializeObject<IOResultBase>(jsonString, settings);
3. 核心原理
Json.NET默认会尝试复用已存在的对象实例(也就是这里的Result.NotStarted静态实例),将JSON中的属性值直接赋值给该实例,导致静态实例被意外修改。自定义转换器通过手动创建新的Result实例,彻底跳过了复用已有实例的逻辑,确保静态实例不会被篡改。
内容的提问来源于stack exchange,提问作者binariti
相关产品推荐
相关产品推荐

