如何让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
相关产品推荐
相关产品推荐

