You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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字段的简洁有效方式:

  1. object类型可以兼容数字、普通字符串、带特殊字符的字符串三种情况,不会触发反序列化异常;
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:32:49