如何使用JsonSerializer反序列化多类型字段?及相关方案是否可行?
问题描述
开发接口时,我使用以下代码进行JSON反序列化:
var responseBodyDeserialized = await JsonSerializer.DeserializeAsync<TResponse>(response.Content.ReadAsStream());
但其中一个字段反序列化时抛出异常,原因是该字段的JSON值存在多种类型:
- 0(数字类型)
- "10"(字符串类型)
- "7+"(带特殊字符的字符串类型)
我尝试将TResponse中对应属性设置为string或int类型,均触发异常。即使使用如下配置的JsonSerializerOptions,将属性设为int类型仍无法处理"7+"这类字符串:
var jsonOptions = new JsonSerializerOptions() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.AllowNamedFloatingPointLiterals };
抛出的异常信息如下:
{"The JSON value could not be converted to System.Int32. Path: $[111].xxxxxx | LineNumber: 0 | BytePositionInLine: 11569963."}
我找到一种解决方案:将该属性设为object类型以接收int或string类型的JSON值,之后通过AutoMapper库将其转换为目标DTO的字符串属性,映射代码如下:
CreateMap<FeedElemDto, ResultDto>() .ForMember(dest => dest.xxxx, opt => opt.MapFrom(src => Convert.ToString(src.xxxx)));
想请教该方案是否可行?
解决方案分析
这个方案完全可行,是处理这类多类型JSON字段的简洁有效方式:
object类型可以兼容数字、普通字符串、带特殊字符的字符串三种情况,不会触发反序列化异常;- AutoMapper中用
Convert.ToString()转换时,能把int类型的0转为"0",字符串类型的"10"、"7+"直接保留原样,完全匹配需求。
另外提供两种替代方案供你根据场景选择:
方案1:自定义JsonConverter
编写自定义转换器,在反序列化阶段直接将多类型值转为string:
public class MultiTypeToStringConverter : JsonConverter<string> { public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return reader.TokenType switch { JsonTokenType.Number => reader.GetInt32().ToString(), JsonTokenType.String => reader.GetString(), _ => throw new JsonException("不支持的JSON令牌类型") }; } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { writer.WriteStringValue(value); } }
在TResponse的对应属性上标记转换器:
[JsonConverter(typeof(MultiTypeToStringConverter))] public string Xxxxx { get; set; }
这样反序列化后直接得到string类型的属性值,无需后续映射转换。
方案2:使用JsonElement类型
将属性设为JsonElement类型,它可以接收任意JSON类型的值,之后手动转换:
public JsonElement Xxxxx { get; set; }
转换逻辑示例:
var targetValue = Xxxxx.ValueKind switch { JsonValueKind.Number => Xxxxx.GetInt32().ToString(), JsonValueKind.String => Xxxxx.GetString(), _ => throw new InvalidOperationException("不支持的数值类型") };
这种方式比object类型更具类型安全性,能明确判断JSON值的具体类型。
内容的提问来源于stack exchange,提问作者Nmaster88
相关产品推荐
相关产品推荐

