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

使用ASP.NET Core MongoDB驱动反序列化时遇JsonException求助

ASP.NET Core MongoDB驱动反序列化报错:'O' is an invalid start of a value

问题概述

使用ASP.NET Core MongoDB驱动反序列化BSON文档时,调用JsonSerializer.DeserializeAsync抛出System.Text.Json.JsonException,错误信息为“'O' is an invalid start of a value”,已验证JSON结构和MongoDB文档仍未解决。当前需保存动态Schema的JSON文档,采用先序列化JSON再转BSON存储、读取时转JSON再反序列化的实现方式。

错误堆栈

System.Text.Json.JsonException: 'O' is an invalid start of a value. Path: $._id | LineNumber: 0 | BytePositionInLine: 10.
 ---> System.Text.Json.JsonReaderException: 'O' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 10.
   at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
   at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
   at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
   at System.Text.Json.Utf8JsonReader.Read()
   at System.Text.Json.Utf8JsonReader.Skip()
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)

相关代码

控制器代码

[HttpGet("{id}")]
public async Task<ActionResult<ProjectIdentification>> GetProjectById(string id)
{
    var project = await _projectService.GetProjectById(id);
    if (project == null)
    {
        return NotFound();
    }
    return Ok(project.ToJson());
}

实体类代码

public class ProjectIdentification
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? Id { get; set; } = ObjectId.GenerateNewId().ToString();

    public string? version { get; set; }
    public Object[] content { get; set; }
    public Object[] columns { get; set; }
    public Theme theme { get; set; }
}

服务层代码

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

    BsonDocument bsonDocument = BsonDocument.Parse(serializedJson);

    await _collection.InsertOneAsync(bsonDocument);
}

public async Task<ProjectIdentification> GetProjectById(string id)
{
    var filter = Builders<BsonDocument>.Filter.Eq("_id", ObjectId.Parse(id));
    var result = await _collection.Find(filter).FirstOrDefaultAsync();
    Console.Write(result);
    if (result != null)
    {
        return JsonSerializer.Deserialize<ProjectIdentification>(result.ToJson());
    }

    return 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"
  }
}

解决思路与建议

1. 错误根源

问题出在result.ToJson()生成的是MongoDB扩展JSON格式(如{"$oid": "xxx"}),而System.Text.Json无法识别这种非标准的JSON结构,解析到$oid的'O'字符时抛出错误。

2. 解决方案一:使用MongoDB驱动直接反序列化BSON

无需将BSON转JSON再反序列化,直接用MongoDB驱动的BsonSerializer完成BSON到实体类的转换,这是最直接的方案:
修改服务层的GetProjectById方法:

public async Task<ProjectIdentification> GetProjectById(string id)
{
    var filter = Builders<BsonDocument>.Filter.Eq("_id", ObjectId.Parse(id));
    var result = await _collection.Find(filter).FirstOrDefaultAsync();
    if (result != null)
    {
        // 使用MongoDB驱动的序列化器直接转换
        return BsonSerializer.Deserialize<ProjectIdentification>(result);
    }
    return null;
}

同时,添加实体类的Bson映射配置(可在Startup/Program中初始化):

BsonClassMap.RegisterClassMap<ProjectIdentification>(cm =>
{
    cm.AutoMap();
    cm.MapIdMember(c => c.Id)
      .SetSerializer(new StringSerializer(BsonType.ObjectId));
});

3. 解决方案二:转换BSON为标准JSON

如果坚持要转JSON再用System.Text.Json解析,需要将MongoDB扩展JSON转换为标准JSON,可使用JsonWriterSettings配置:
修改GetProjectById中的result.ToJson():

var json = result.ToJson(new JsonWriterSettings
{
    OutputMode = JsonOutputMode.Strict
});
return JsonSerializer.Deserialize<ProjectIdentification>(json);

JsonOutputMode.Strict会将$oid这类扩展类型直接转换为字符串,生成标准JSON格式,让System.Text.Json可以正常解析。

4. 优化动态Schema的处理

针对动态Schema的需求,实体类中的content和columns字段可以用BsonDocument[]替代Object[],这样MongoDB驱动可以更好地处理动态结构,同时避免序列化/反序列化时的类型问题:

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

如果需要将BsonDocument转换为.NET对象,可后续再用BsonSerializer或手动转换为动态对象(如dynamic或Dictionary<string, object>)。


内容的提问来源于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 01:55:56