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

.NET API中System.Text.Json.JsonElement MongoDB序列化报错求助

解决.NET API中MongoDB序列化System.Text.Json.JsonElement的异常

在.NET API中构建包含columns和content的动态模型时,将数据存入MongoDB触发MongoDB.Bson.BsonSerializationException,错误提示:

System.Text.Json.JsonElement类型未在此ObjectSerializer实例中配置为可序列化类型

错误堆栈信息

MongoDB.Bson.BsonSerializationException: An error occurred while serializing the content property of class pm_management.API.Domain.Models.ProjectIdentification: Type System.Text.Json.JsonElement is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer.
 ---> MongoDB.Bson.BsonSerializationException: Type System.Text.Json.JsonElement is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer.
   at MongoDB.Bson.Serialization.Serializers.ObjectSerializer.SerializeDiscriminatedValue(BsonSerializationContext context, BsonSerializationArgs args, Object value, Type actualType)
   at MongoDB.Bson.Serialization.Serializers.ObjectSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize[TValue](IBsonSerializer`1 serializer, BsonSerializationContext context, TValue value)
   at MongoDB.Bson.Serialization.Serializers.EnumerableSerializerBase`2.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
   at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value)
   at MongoDB.Bson.Serialization.BsonClassMapSerializer`1.SerializeMember(BsonSerializationContext context, Object obj, BsonMemberMap memberMap)

相关代码

模型类及扩展方法

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Globalization;
using System.Text.Json;

namespace pm_management.API.Domain.Models
{
    [BsonIgnoreExtraElements]
    public class ProjectIdentification
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string? Id { get; set; }
        public Object[] content { get; set; }

        public Object[] columns { get; set; }

        public Theme theme { get; set; }
        public void SetContentAndColumns(string contentJson, string columnsJson)
        {
            content = JsonSerializer.Deserialize<Object[]>(contentJson);
            columns = JsonSerializer.Deserialize<Object[]>(columnsJson);
        }

    }
    public static class BsonExtensions
    {
        public static BsonDocument ToBsonDocument(this JsonElement e, bool writeRootArrayAsDocument = false, bool tryParseDateTimes = false) =>
            e.ValueKind switch
            {
                JsonValueKind.Object =>
                    new(e.EnumerateObject().Select(p => new BsonElement(p.Name, p.Value.ToBsonValue(tryParseDateTimes)))),
                JsonValueKind.Array when writeRootArrayAsDocument =>
                    new(e.EnumerateArray().Select((v, i) => new BsonElement(i.ToString(NumberFormatInfo.InvariantInfo), v.ToBsonValue(tryParseDateTimes)))),
                _ => throw new NotSupportedException($"ToBsonDocument: {e}"),
            };

        public static BsonValue ToBsonValue(this JsonElement e, bool tryParseDateTimes = false) =>
            e.ValueKind switch
            {
                JsonValueKind.String when tryParseDateTimes && e.TryGetDateTime(out var v) => BsonValue.Create(v),
                JsonValueKind.String => BsonValue.Create(e.GetString()),
                JsonValueKind.Number when e.TryGetInt32(out var v) => BsonValue.Create(v),
                JsonValueKind.Number when e.TryGetInt64(out var v) => BsonValue.Create(v),
                JsonValueKind.Number when e.TryGetDouble(out var v) => BsonValue.Create(v),
                JsonValueKind.Null => BsonValue.Create(null),
                JsonValueKind.True => BsonValue.Create(true),
                JsonValueKind.False => BsonValue.Create(false),
                JsonValueKind.Array => new BsonArray(e.EnumerateArray().Select(v => v.ToBsonValue(tryParseDateTimes))),
                JsonValueKind.Object => e.ToBsonDocument(false, tryParseDateTimes),
                _ => throw new NotSupportedException($"ToBsonValue: {e}"),
            };
    }
}

仓储代码

private readonly IMongoCollection<ProjectIdentification> _collection;

public ProjectIdentificationRepository(IOptions<MongoDbSettings> mongoDbSettings)
{
    var mongoClient = new MongoClient(
        mongoDbSettings.Value.ConnectionString);

    var mongoDatabase = mongoClient.GetDatabase(
        mongoDbSettings.Value.DatabaseName);

    _collection = mongoDatabase.GetCollection<ProjectIdentification>("Project");
}

public async Task AddProject(ProjectIdentification project)
{
    string serializedJson = JsonSerializer.Serialize(project, new JsonSerializerOptions
    {
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
    });

    ProjectIdentification deserializedProject = JsonSerializer.Deserialize<ProjectIdentification>(serializedJson);

    await _collection.InsertOneAsync(deserializedProject);
}

public async Task<ProjectIdentification> GetProjectById(string id)
{
    var filter = Builders<ProjectIdentification>.Filter.Eq("_id", ObjectId.Parse(id));
    var result = await _collection.Find(filter).FirstOrDefaultAsync();

    return result ?? null;
}

示例数据

{
  "_id": { "$oid": "65edc0c6482da8bd8368fbbf" },
  "Id": "65edc0c6482da8bd8368fbbe",
  "content": [
    {
      "id": "z5LllRt-NoiGkoisa_2tN",
      "type": "image",
      "data": {
        "style": "circle",
        "image": "/images/profile.jpg"
      }
    },
    {
      "id": "QfAFa0golVKIImL764OCO",
      "type": "text",
      "data": {
        "headline": "Horst Karacho",
        "description": "My name is Horst :)",
        "rank":"test",
        "anotherfield":"tesst"
      }
    },
    {
      "id": "j3ofcLmYExoG0AS_yoRq0",
      "type": "text",
      "data": {
        "headline": "Lorem Ipsum",
        "description": "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna...",
        "details": {
          "author": "Unknown",
          "publishedDate": "2023-01-15",
          "wordCount": 245
        }
      }
    }
  ],
  "columns": [
    {
      "id": "mOceUBR-oB5xEzfstycFh",
      "content": [
        "qkx4WlS5XkUZcfTpy9rN0",
        "qkx4WlS5XkUZcfTpy9rN1",
        "qkx4WlS5XkUZcfTpy9rN11",
        "qkx4WlS5XkUZcfTpy9rN12",
        "qkx4WlS5XkUZcfTpy9rN3",
        "qkx4WlS5XkUZcfTpy9rN4",
        "qkx4WlS5XkUZcfTpy9rN5",
        "qkx4WlS5XkUZcfTpy9rN6",
        "qkx4WlS5XkUZcfTpy9rN7",
        "qkx4WlS5XkUZcfTpy9rN8",
        "qkx4WlS5XkUZcfTpy9rN9"
      ]
    }
  ],
  "theme": {
    "HighlightColor": "#3f51b5",
    "HeadlineColor": "#95A5A6",
    "HeadlineFontType": "Roboto",
    "HeadlineFontSize": "1.8em",
    "HeadlineFontWeight": "600",
    "HeadlineBorderType": "dashed",
    "TextColor": "#333",
    "TextFontType": "Source Sans Pro",
    "TextFontSize": "1em",
    "TextFontWeight": "200"
  }
}

问题根源

使用JsonSerializer.Deserialize<Object[]>反序列化时,实际返回的是JsonElement类型的数组,而MongoDB的默认ObjectSerializer不支持直接序列化JsonElement类型。此外,AddProject方法中多余的序列化-反序列化操作会加剧这个问题,导致对象类型被转换为JsonElement。

解决方案

1. 自定义JsonElement的Bson序列化器

创建序列化器将JsonElement转换为MongoDB支持的BsonValue:

using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using System.Text.Json;

public class JsonElementBsonSerializer : SerializerBase<JsonElement>
{
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, JsonElement value)
    {
        var bsonValue = value.ToBsonValue();
        context.Writer.WriteBsonValue(bsonValue);
    }

    public override JsonElement Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
    {
        var bsonValue = context.Reader.ReadBsonValue();
        using var tempDoc = new BsonDocument("val", bsonValue);
        var json = tempDoc.ToJson();
        using var doc = JsonDocument.Parse(json);
        return doc.RootElement.GetProperty("val");
    }
}

在应用启动时注册该序列化器:

BsonSerializer.RegisterSerializer(new JsonElementBsonSerializer());

2. 修改模型属性类型

将模型中的Object[]改为JsonElement[],明确类型:

public JsonElement[] content { get; set; }
public JsonElement[] columns { get; set; }

同时更新SetContentAndColumns方法的反序列化逻辑:

public void SetContentAndColumns(string contentJson, string columnsJson)
{
    content = JsonSerializer.Deserialize<JsonElement[]>(contentJson);
    columns = JsonSerializer.Deserialize<JsonElement[]>(columnsJson);
}

3. 移除多余的序列化循环

删除AddProject中不必要的序列化-反序列化步骤,直接使用传入的对象:

public async Task AddProject(ProjectIdentification project)
{
    await _collection.InsertOneAsync(project);
}

完成以上步骤后,MongoDB就能正确序列化JsonElement类型的属性,解决异常问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:08:09