SignalR传输MyDataClass时System.Text.Json序列化反序列化异常问题
解决SignalR传输MyDataClass时的序列化无限循环与反序列化问题
问题根源分析
你遇到的序列化无限循环,本质是自定义JsonConverter在序列化MyDataClass时触发了递归调用:因为类上标记了[JsonConverter]特性,当转换器的Write方法里尝试序列化MyDataClass实例时,会再次触发这个转换器,陷入无限循环。
而反序列化时Value变成JsonElement,是因为System.Text.Json默认会把未知类型的object序列化为JsonElement,无法自动映射回你需要的具体类型。
修复方案:正确实现自定义JsonConverter
修改你的MyDataClassConverter,在序列化时手动处理属性避免递归;反序列化时利用Format属性解析Value到对应类型,同时保留类上的[JsonConverter]特性实现全局配置。
1. MyDataClass定义(保留特性)
[JsonConverter(typeof(MyDataClassConverter))] public class MyDataClass { public string Format { get; set; } public object Value { get; set; } }
2. 正确的自定义转换器实现
public class MyDataClassConverter : JsonConverter<MyDataClass> { public override MyDataClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 先将JSON读为JsonElement,再提取属性解析 using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; var format = root.GetProperty("Format").GetString(); var valueJson = root.GetProperty("Value").ToString(); // 用FormatHelper将字符串转为对应类型对象 var value = FormatHelper.GetObjectValue(valueJson, format); return new MyDataClass { Format = format, Value = value }; } public override void Write(Utf8JsonWriter writer, MyDataClass value, JsonSerializerOptions options) { // 手动序列化属性,避免触发转换器递归 writer.WriteStartObject(); writer.WriteString("Format", value.Format); // 根据Format获取对应类型,精准序列化Value var targetType = GetTypeFromFormat(value.Format); JsonSerializer.Serialize(writer, value.Value, targetType, options); writer.WriteEndObject(); } // 辅助方法:根据Format字符串匹配对应的Type private Type GetTypeFromFormat(string format) { // 这里根据你的Format规则实现映射,示例如下: return format switch { "int" => typeof(int), "string" => typeof(string), "datetime" => typeof(DateTime), "bool" => typeof(bool), // 补充你需要的其他类型映射 _ => typeof(object) }; } }
核心要点
- 序列化防递归:Write方法不直接序列化
MyDataClass实例,而是手动写入Format和Value属性,序列化Value时指定具体类型,绕开自身转换器的递归调用。 - 反序列化精准解析:先将JSON读为
JsonElement,提取Format后用FormatHelper把Value的JSON字符串转成对应类型对象,解决JsonElement无法直接转换的问题。
效果验证
现在给MyDataClass加上[JsonConverter]特性后,不管是序列化单个实例还是列表,都不会出现无限循环;反序列化时Value也能正确解析为对应类型,无需再单独在反序列化时指定转换器,实现简洁的全局配置。
内容的提问来源于stack exchange,提问作者Foxhunt
相关产品推荐
相关产品推荐

