UnixEpochDateTimeConverter反序列化报错:Number类型无法作为字符串读取
问题根因与解决方案
根因说明
你引入的UnixEpochDateTimeConverter内部通过reader.GetString()取值,说明该转换器的设计目标是适配字符串格式的Unix时间戳输入,但你调用的接口返回的时间戳为JSON数值(Number)类型,Utf8JsonReader遇到数值类型Token时调用GetString()就会抛出你遇到的System.InvalidOperationException异常。
可落地解决方案(均不需要修改原有转换器代码)
方案1:使用.NET内置的Unix时间戳转换器
.NET 6及以上版本的System.Text.Json已经内置了支持秒级、毫秒级Unix时间戳的原生转换器,直接替换你当前注册的自定义转换器即可,兼容数值类型的时间戳输入:
var jsonOptions = new JsonSerializerOptions { Converters = { // 处理毫秒级Unix时间戳用这个 new UnixMillisecondsDateTimeConverter(), // 如果是秒级时间戳用下面这个 // new UnixSecondsDateTimeConverter() } };
方案2:新增包装转换器适配数值输入
如果你需要保留当前使用的官方转换器实现,可以新增一个包装转换器,预处理数值类型的输入后再转交给原有转换器处理:
public class NumberCompatibleUnixEpochConverterWrapper : JsonConverter<DateTime> { private readonly UnixEpochDateTimeConverter _innerConverter = new UnixEpochDateTimeConverter(); public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 输入为数值类型时先转成字符串格式,适配原有转换器的逻辑 if (reader.TokenType == JsonTokenType.Number) { long timestampNum = reader.GetInt64(); string timestampStr = timestampNum.ToString(); // 构造符合原有转换器输入要求的Reader byte[] stringPayload = System.Text.Encoding.UTF8.GetBytes($"\"{timestampStr}\""); var stringReader = new Utf8JsonReader(stringPayload); stringReader.Read(); return _innerConverter.Read(ref stringReader, typeToConvert, options); } // 输入已经是字符串类型时直接走原有逻辑 return _innerConverter.Read(ref reader, typeToConvert, options); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { _innerConverter.Write(writer, value, options); } }
配置时只需要在JsonSerializerOptions的转换器列表里注册这个包装类即可,不需要修改原有转换器的任何代码。
方案3:调整接口返回格式(仅适用于接口可控的场景)
如果对应的接口是你自己维护的,可以把返回报文中的时间戳从数值类型改为字符串类型,C#端不需要做任何修改即可兼容。
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

