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

如何让System.Text.Json将object类型字段反序列化为原始类型?

问题产生原因

这是System.Text.Json和Newtonsoft.Json的默认反序列化策略差异导致的:

  • Newtonsoft.Json反序列化object类型的字段/属性时,会自动根据JSON值的类型推断映射到对应的.NET基元类型(字符串、整数、布尔值等)
  • System.Text.Json出于避免隐式类型转换引发精度损失、类型不符问题的保守设计,反序列化object类型时默认会统一返回JsonElement类型实例,不会自动转成原始基元类型,所以才会出现你遇到的类型不匹配异常。
解决方案

有两种常用的实现方式,可以根据你的使用场景选择:

方式1:自定义全局转换器,无需修改POCO类

你可以实现一个针对object类型的自定义JsonConverter,在序列化时保留原始类型,反序列化时自动把JsonElement转成对应的基元类型,代码如下:

using System.Text.Json;
using System.Text.Json.Serialization;

public class ObjectToPrimitiveConverter : JsonConverter<object>
{
    public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return reader.TokenType switch
        {
            JsonTokenType.True => true,
            JsonTokenType.False => false,
            JsonTokenType.Number when reader.TryGetInt32(out int intValue) => intValue,
            JsonTokenType.Number when reader.TryGetInt64(out long longValue) => longValue,
            JsonTokenType.Number => reader.GetDouble(),
            JsonTokenType.String => reader.GetString(),
            JsonTokenType.Null => null,
            // 剩余复杂类型走默认反序列化逻辑
            _ => JsonSerializer.Deserialize(ref reader, typeToConvert, options)
        };
    }

    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
    {
        // 序列化时用值的实际类型序列化,避免丢失类型信息
        JsonSerializer.Serialize(writer, value, value.GetType(), options);
    }
}

使用时把转换器添加到JsonSerializerOptions中即可:

var options = new SJ.JsonSerializerOptions
{
    Converters = { new ObjectToPrimitiveConverter() }
};
// 序列化、反序列化都传入该配置
var s = SJ.JsonSerializer.Serialize(nvp, options);
var d = SJ.JsonSerializer.Deserialize<NVP>(s, options);

方式2:给POCO属性加特性,无需使用者额外配置

如果你不希望强制类库使用者手动配置序列化选项,可以直接给POCO里的object类型属性加上转换器特性,Newtonsoft.Json会自动忽略不识别的System.Text.Json特性,不会影响兼容性:

public class NVP
{
    public string Name { get; set; }
    [SJ.JsonConverter(typeof(ObjectToPrimitiveConverter))]
    public object Value { get; set; }
}

配置完成后你的两个单元测试都可以正常通过。

内容的提问来源于stack exchange,提问作者Jeff Dege

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 11:24:04