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

如何在C#与MongoDB中实现TimeOnly的序列化与反序列化

.NET 6中MongoDB 4.4对TimeOnly?类型的序列化/反序列化问题及解决方案

问题场景

  • 环境:.NET 6 + C#,MongoDB 4.4
  • 模型类使用TimeOnly?类型,存储到MongoDB后生成的文档结构如下:
"defaultTime" : {
    "hour" : 15,
    "minute" : 15,
    "second" : 0,
    "millisecond" : 0,
    "ticks" : NumberLong(549000000000)
}
  • 从MongoDB读取数据时触发反序列化异常:

System.FormatException: 反序列化Models.Customer类的DefaultTime属性时出错:无法反序列化值类型System.TimeOnly。

---> MongoDB.Bson.BsonSerializationException: 无法反序列化值类型System.TimeOnly。

在 MongoDB.Bson.Serialization.BsonClassMapSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)

在 MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize[TValue](IBsonSerializer`1 serializer, BsonDeserializationContext context)

在 MongoDB.Bson.Serialization.Serializers.NullableSerializer`1.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)

在 MongoDB.Bson.Serialization.Serializers.SerializerBase`1.MongoDB.Bson.Serialization.IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)

在 MongoDB.Bson.Serialization.IBsonSerializerExtensions.Deserialize(IBsonSerializer serializer, BsonDeserializationContext context)

在 MongoDB.Bson.Serialization.BsonClassMapSerializer`1.DeserializeMemberValue(BsonDeserializationContext context, BsonMemberMap memberMap)

解决方案(已验证)

通过在MongoDB中直接存储TimeOnly对应的ticks值规避序列化问题,存储结构简化为:

"defaultTime" : NumberLong(549000000000)

需要自定义MongoDB序列化器实现ticks与TimeOnly?的双向转换:

自定义序列化器代码

public class TimeOnlyNullableSerializer : IBsonSerializer<TimeOnly?>
{
    public Type ValueType => typeof(TimeOnly?);

    public TimeOnly? Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonType = context.Reader.GetCurrentBsonType();
        if (bsonType == BsonType.Null)
        {
            context.Reader.ReadNull();
            return null;
        }
        if (bsonType == BsonType.Int64)
        {
            var ticks = context.Reader.ReadInt64();
            return TimeOnly.FromTicks(ticks);
        }
        throw new NotSupportedException($"无法从类型{bsonType}反序列化为TimeOnly?");
    }

    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TimeOnly? value)
    {
        if (!value.HasValue)
        {
            context.Writer.WriteNull();
            return;
        }
        context.Writer.WriteInt64(value.Value.Ticks);
    }

    object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        return Deserialize(context, args);
    }

    void IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
    {
        Serialize(context, args, (TimeOnly?)value);
    }
}

注册序列化器

在MongoDB客户端初始化时绑定序列化器:

var clientSettings = MongoClientSettings.FromConnectionString("你的MongoDB连接字符串");
var classMap = BsonClassMap.LookupClassMap(typeof(Customer));
classMap.GetMemberMap(c => c.DefaultTime)
    .SetSerializer(new TimeOnlyNullableSerializer());
BsonSerializer.RegisterClassMap(classMap);

var client = new MongoClient(clientSettings);

通过上述配置,即可实现TimeOnly?类型与MongoDB中ticks值的正常序列化、反序列化,解决原异常问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:45:46