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

在ASP.NET Core 6中如何高效将JsonElement转换为BsonDocument?

JsonElement转BsonDocument的高效实现方案

直接序列化字符串再解析的方式确实会产生额外性能开销,下面提供几种更高效的实现思路:

方案一:直接通过BsonWriter构建BsonDocument

这种方式跳过中间字符串转换,直接将JsonElement的节点映射为Bson类型,性能最优。

using MongoDB.Bson;
using MongoDB.Bson.IO;
using System.Text.Json;

public static BsonDocument ConvertJsonElementToBson(JsonElement element)
{
    using var stream = new MemoryStream();
    using var bsonWriter = new BsonBinaryWriter(stream);
    var writer = new BsonWriter(bsonWriter);

    WriteElementToBson(writer, element);

    stream.Position = 0;
    return BsonDocument.ReadFrom(bsonWriter);
}

private static void WriteElementToBson(BsonWriter writer, JsonElement element)
{
    switch (element.ValueKind)
    {
        case JsonValueKind.Object:
            writer.WriteStartDocument();
            foreach (var prop in element.EnumerateObject())
            {
                writer.WriteName(prop.Name);
                WriteElementToBson(writer, prop.Value);
            }
            writer.WriteEndDocument();
            break;
        case JsonValueKind.Array:
            writer.WriteStartArray();
            foreach (var item in element.EnumerateArray())
            {
                WriteElementToBson(writer, item);
            }
            writer.WriteEndArray();
            break;
        case JsonValueKind.String:
            writer.WriteString(element.GetString());
            break;
        case JsonValueKind.Number:
            if (element.TryGetInt32(out var intVal))
                writer.WriteInt32(intVal);
            else if (element.TryGetInt64(out var longVal))
                writer.WriteInt64(longVal);
            else if (element.TryGetDouble(out var doubleVal))
                writer.WriteDouble(doubleVal);
            else if (element.TryGetDecimal(out var decVal))
                writer.WriteDecimal128(new Decimal128(decVal));
            break;
        case JsonValueKind.True:
        case JsonValueKind.False:
            writer.WriteBoolean(element.GetBoolean());
            break;
        case JsonValueKind.Null:
            writer.WriteNull();
            break;
        case JsonValueKind.Undefined:
            writer.WriteUndefined();
            break;
        default:
            throw new NotSupportedException($"不支持的JsonValueKind类型:{element.ValueKind}");
    }
}

方案二:反序列化为强类型对象再转换

如果JsonElement对应的JSON结构是固定的,可以先反序列化为具体的DTO类,再通过BsonDocument.Create生成BsonDocument,代码更简洁:

// 假设已有对应的DTO类MyModel
var model = myJsonElement.Deserialize<MyModel>();
var bsonDoc = BsonDocument.Create(model);

如果是动态结构,可自定义转换器将JsonElement转为Dictionary<string, object>后再转换:

var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true,
    Converters = { new JsonElementToObjectConverter() }
};
var dynamicObj = myJsonElement.Deserialize<Dictionary<string, object>>(options);
var bsonDoc = BsonDocument.Create(dynamicObj);

// 自定义转换器:将JsonElement转为对应.NET类型
public class JsonElementToObjectConverter : JsonConverter<object>
{
    public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        return ConvertElement(doc.RootElement);
    }

    private object ConvertElement(JsonElement element)
    {
        switch (element.ValueKind)
        {
            case JsonValueKind.Object:
                return element.EnumerateObject()
                    .ToDictionary(kv => kv.Name, kv => ConvertElement(kv.Value));
            case JsonValueKind.Array:
                return element.EnumerateArray().Select(ConvertElement).ToList();
            case JsonValueKind.String:
                return element.GetString();
            case JsonValueKind.Number:
                if (element.TryGetInt64(out var longVal)) return longVal;
                if (element.TryGetDouble(out var doubleVal)) return doubleVal;
                return element.GetDecimal();
            case JsonValueKind.True:
            case JsonValueKind.False:
                return element.GetBoolean();
            case JsonValueKind.Null:
                return null;
            default:
                throw new NotSupportedException();
        }
    }

    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

方案三:借助Newtonsoft.Json中转(适合快速实现)

如果项目已引用Newtonsoft.Json,可先将JsonElement转为JObject再生成BsonDocument,实现简单:

using Newtonsoft.Json.Linq;

var jObj = JObject.Parse(myJsonElement.GetRawText());
var bsonDoc = BsonDocument.Create(jObj);

这种方式虽有中间转换,但代码量少,适合性能要求不极端的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:17:20