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

.NET 6中使用System.Text.Json序列化BsonDocument时出现类型转换错误

问题描述

我定义了如下C#类:

public class Product
{
    public string ProductName { get; set; }
    public int ProductCount { get; set; }
    public BsonDocument ProductMetadata { get; set; }
}

其中BsonDocument来自MongoDB.Driver。我的API代码如下:

// GET: api/<ProductController>
[HttpGet]
public Product Get()
{
    Product prod = new Product();
    prod.ProductName = "Test";
    prod.ProductCount = 20;
    var doc = new BsonDocument
    {
        { "metadata1", "val1" }
    };
    prod.ProductMetadata = doc;
    return prod;
}

调用该Get接口时出现以下错误:

An unhandled exception occurred while processing the request.
InvalidCastException: Unable to cast object of type 'MongoDB.Bson.BsonString' to type 'MongoDB.Bson.BsonBoolean'.
System.Text.Json.Serialization.Metadata.JsonPropertyInfo<T>.GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer)
System.Text.Json.Serialization.Converters.ObjectDefaultConverter<T>.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state)
System.Text.Json.Serialization.JsonConverter<T>.TryWrite(Utf8JsonWriter writer, ref T value, JsonSerializerOptions options, ref WriteStack state)
System.Text.Json.Serialization.Metadata.JsonPropertyInfo<T>.GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer)
System.Text.Json.Serialization.Converters.ObjectDefaultConverter<T>.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state)
....

序列化器试图将metadata1转换为布尔类型,这是什么原因?

问题原因

ASP.NET Core默认使用System.Text.Json做序列化,但它没有内置BsonDocument的处理逻辑。BsonDocument的元素是BsonValue类型,System.Text.Json反射序列化时会遍历BsonValue的所有属性,包括AsBoolean这类强类型转换属性——当BsonValue实际是字符串类型(比如你的metadata1对应BsonString),访问AsBoolean就会触发类型转换异常,这就是错误的根源。

解决方法

方案1:全局配置自定义转换器

为BsonDocument编写System.Text.Json转换器,让序列化器正确识别各类型的BsonValue:

public class BsonDocumentJsonConverter : JsonConverter<BsonDocument>
{
    public override BsonDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 若需支持反序列化,可在此实现逻辑
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, BsonDocument value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        foreach (var element in value)
        {
            writer.WritePropertyName(element.Key);
            WriteBsonValue(writer, element.Value);
        }
        writer.WriteEndObject();
    }

    private void WriteBsonValue(Utf8JsonWriter writer, BsonValue value)
    {
        switch (value.BsonType)
        {
            case BsonType.String:
                writer.WriteStringValue(value.AsString);
                break;
            case BsonType.Int32:
                writer.WriteNumberValue(value.AsInt32);
                break;
            case BsonType.Boolean:
                writer.WriteBooleanValue(value.AsBoolean);
                break;
            case BsonType.Double:
                writer.WriteNumberValue(value.AsDouble);
                break;
            // 根据业务需求添加其他Bson类型的处理
            default:
                writer.WriteStringValue(value.ToString());
                break;
        }
    }
}

然后在Program.cs中注册转换器:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new BsonDocumentJsonConverter());
    });

方案2:局部转换为通用类型

在返回前把BsonDocument转换成System.Text.Json能正常处理的类型,比如Dictionary<string, object>或匿名对象:

[HttpGet]
public object Get()
{
    Product prod = new Product();
    prod.ProductName = "Test";
    prod.ProductCount = 20;
    var doc = new BsonDocument
    {
        { "metadata1", "val1" }
    };
    
    // 转换为Dictionary
    var metadataDict = doc.ToDictionary(kv => kv.Key, kv => kv.Value.ToObject<object>());
    
    return new 
    {
        prod.ProductName,
        prod.ProductCount,
        ProductMetadata = metadataDict
    };
}

这种方式无需修改全局配置,适合单个接口的局部处理。

方案3:切换到Newtonsoft.Json序列化

ASP.NET Core也支持使用Newtonsoft.Json(Json.NET),它对BsonDocument的兼容性更好:

  1. 安装Microsoft.AspNetCore.Mvc.NewtonsoftJson包
  2. 在Program.cs中配置:
builder.Services.AddControllers()
    .AddNewtonsoftJson();

之后BsonDocument会被自动序列化为对应的JSON结构,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 03:14:56