如何让Newtonsoft Json反序列化不可写的数组属性?
解决Json.NET反序列化只读数组属性的问题
针对你遇到的只读数组属性Bar无法被Json.NET正确反序列化的问题,可以通过自定义Json转换器实现逐个元素赋值到已初始化的数组实例中,具体步骤如下:
1. 实现自定义数组转换器
创建一个通用转换器,用于处理只读数组的反序列化逻辑:
public class ReadOnlyArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(T[]); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jsonArray = JArray.Load(reader); var existingArray = existingValue as T[]; // 如果没有已存在的数组实例,直接返回新数组 if (existingArray == null) return jsonArray.ToObject<T[]>(); // 逐个将JSON数组元素赋值到已有数组的对应索引 for (int i = 0; i < Math.Min(jsonArray.Count, existingArray.Length); i++) { existingArray[i] = jsonArray[i].ToObject<T>(serializer); } return existingArray; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 序列化沿用默认逻辑 serializer.Serialize(writer, value); } }
2. 应用转换器
有两种方式可以让Json.NET使用这个转换器:
方式一:标记在目标属性上
直接给TestClass的Bar属性添加特性:
/// <summary> /// 无法修改的外部类 /// </summary> public class TestClass { public string Foo { get; set; } [JsonConverter(typeof(ReadOnlyArrayConverter<int>))] public int[] Bar { get; } = new int[3]; }
方式二:全局注册转换器
如果多个类需要处理类似场景,可以在序列化配置中全局添加转换器:
var settings = new JsonSerializerSettings(); settings.Converters.Add(new ReadOnlyArrayConverter<int>()); // 序列化 string json = JsonConvert.SerializeObject(testClass, settings); // 反序列化 TestClass result = JsonConvert.DeserializeObject<TestClass>(json, settings)!;
效果验证
经过上述修改后,反序列化得到的result.Bar[0]会正确赋值为3,和原对象的数组内容一致。转换器会优先复用类中已初始化的数组实例,避免创建新数组,同时自动处理索引越界问题(只赋值到已有数组的长度范围内)。
内容的提问来源于stack exchange,提问作者Klamsi
相关产品推荐
相关产品推荐

