序列化VMoney类时出现无限循环问题求助
问题分析与解决方案
核心问题原因
- 未使用转换器时子类字段丢失:Json序列化默认仅处理基类
VMoney声明的成员,派生类LimitedVMoney的BeginDateTime、EndDateTime属于子类独有字段,默认序列化逻辑无法识别多态类型,因此被忽略。 - 使用转换器后基类无限循环:自定义
VMoneyConverter的WriteJson方法中,若直接调用serializer.Serialize(writer, value),会触发转换器自身的递归调用(因为转换器绑定了VMoney类型),导致无限循环崩溃。
解决方案1:修改自定义转换器,避免递归调用
直接在转换器中区分基类与子类实例,手动构建JSON对象输出,绕过递归调用:
public class VMoneyConverter : JsonConverter<VMoney> { public override void WriteJson(JsonWriter writer, VMoney value, JsonSerializer serializer) { var jsonObject = new JObject(); // 写入基类公共字段 jsonObject.Add("Value", value.Value); // 判断是否为子类实例,写入额外字段 if (value is LimitedVMoney limitedMoney) { jsonObject.Add("BeginDateTime", limitedMoney.BeginDateTime); jsonObject.Add("EndDateTime", limitedMoney.EndDateTime); } // 直接写入JSON对象,避免触发转换器递归 jsonObject.WriteTo(writer); } public override VMoney ReadJson(JsonReader reader, Type objectType, VMoney existingValue, bool hasExistingValue, JsonSerializer serializer) { var jsonObject = JObject.Load(reader); // 根据是否存在子类字段判断实例类型 if (jsonObject.ContainsKey("BeginDateTime")) { return jsonObject.ToObject<LimitedVMoney>(serializer); } return jsonObject.ToObject<VMoney>(serializer); } }
解决方案2:利用TypeNameHandling处理多态(无需自定义转换器)
如果可以接受序列化结果中包含类型标识字段$type,可以通过配置JsonSerializerSettings自动处理多态类型,无需编写转换器:
// 配置序列化设置 var serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; // 序列化对象 var serializedJson = JsonConvert.SerializeObject(yourVMoneyInstance, serializerSettings); // 反序列化对象 var deserializedObj = JsonConvert.DeserializeObject<VMoney>(serializedJson, serializerSettings);
注意:
TypeNameHandling可能存在反序列化安全风险,若处理不可信输入,需配合SerializationBinder限制允许反序列化的类型。
总结
- 若需避免输出类型标识字段,优先选择自定义转换器方案,核心是手动构建JSON对象,避免触发转换器递归。
- 若项目允许类型标识字段,TypeNameHandling配置更简洁,无需额外编写转换器逻辑。
内容的提问来源于stack exchange,提问作者Weazy
相关产品推荐
相关产品推荐

