ASP.NET Core API向CosmosDB存储半任意JSON出现ValueKind问题
问题原因
你遇到的ValueKind字段问题确实是类型声明+默认序列化机制导致的:
- .NET 内置的
System.Text.Json反序列化时,如果用dynamic接收JSON对象,实际返回的是JsonElement值类型实例 - Cosmos DB SDK序列化这个
JsonElement实例时,没有做特殊适配,只会把它的公开属性ValueKind(一个枚举值,对象类型对应值为1)写入文档,最终就出现了你看到的body结构丢失问题。
解决方案
不需要手动读取请求流、用Utf8JsonReader自行解析,只需要替换body字段的声明类型即可,有两种常用可选方案:
方案1:使用JsonElement类型(最稳定)
直接将Request记录的body字段类型改为JsonElement,这是System.Text.Json的原生JSON节点类型,Cosmos SDK可以正确识别并完整序列化其内部结构,无论body里是嵌套对象、数组、基础类型都不会丢失:
public record Request(string id, string type, string name, JsonElement body);
如果需要校验固定字段、读取body内的属性,调用GetProperty()、GetString()等内置方法即可。
方案2:使用JsonNode类型(动态访问体验更好)
如果你想要和dynamic类似的、可以直接通过属性名访问字段的体验,在.NET 6及以上版本可以用System.Text.Json.Nodes.JsonNode作为body类型:
public record Request(string id, string type, string name, JsonNode body);
改完后你可以直接用postedRequest.body.property1这种动态语法取值,不需要手动调用GetProperty方法,同时也能被Cosmos SDK正确序列化,不会出现结构丢失。
额外注意
你贴的完整代码里GET接口存在异步方法未等待的问题,会导致接口返回Task对象本身而非实际存储的文档,需要补上await关键字并返回Resource属性:
app.MapGet ( "/requests/{type}/{id}", async (Container db, string type, string id) => { var dbResult = await db.ReadItemAsync<Request>(id, new PartitionKey(type)); return Results.Ok(dbResult.Resource); } );
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

