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

如何将含Dictionary属性的文档插入Cosmos DB且不生成Key/Value关键字

根因说明

JSON规范仅支持字符串类型作为对象的键,当.NET序列化器处理键为int等非字符串类型的Dictionary时,默认会将其序列化为包含Key、Value字段的数组结构,就是你现在看到的存储结果。

可行实现方案

方案1:自定义序列化转换器(最推荐,无侵入性)

你可以针对Dictionary<int, T>类型写自定义JsonConverter,直接控制序列化逻辑,不需要修改原有业务代码结构,兼容Newtonsoft.Json和System.Text.Json两种序列化组件:

若你使用Newtonsoft.Json作为Cosmos序列化器

自定义转换器代码:

public class IntKeyDictionaryConverter<TValue> : JsonConverter<Dictionary<int, TValue>>
{
    public override void WriteJson(JsonWriter writer, Dictionary<int, TValue> value, JsonSerializer serializer)
    {
        writer.WriteStartObject();
        foreach (var pair in value)
        {
            writer.WritePropertyName(pair.Key.ToString());
            serializer.Serialize(writer, pair.Value);
        }
        writer.WriteEndObject();
    }

    public override Dictionary<int, TValue> ReadJson(JsonReader reader, Type objectType, Dictionary<int, TValue> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var dict = new Dictionary<int, TValue>();
        var jObj = JObject.Load(reader);
        foreach (var prop in jObj.Properties())
        {
            dict[int.Parse(prop.Name)] = prop.Value.ToObject<TValue>(serializer);
        }
        return dict;
    }
}

之后只要在你的类属性上加特性即可生效:

public class Foo
{
    [JsonConverter(typeof(IntKeyDictionaryConverter<int>))]
    public Dictionary<int, int> dictionary { get; }
}
若你使用System.Text.Json作为Cosmos序列化器

自定义转换器逻辑和上面一致,只是继承JsonConverter<Dictionary<int, TValue>>实现对应的读写方法,之后可以选择给属性加[JsonConverter]特性,或者在创建CosmosClient时将转换器注册到全局序列化配置中,对所有Dictionary<int, T>生效。

方案2:提前转换字典键类型(简单易实现)

直接将属性定义修改为键为字符串的Dictionary,赋值时将int键转为字符串存入:

public class Foo
{
    public Dictionary<string, int> dictionary { get; }
}

序列化器遇到字符串键的Dictionary会直接生成你期望的对象结构,读取时如果需要用int键,只要调用int.Parse()转换即可,性能损耗几乎可以忽略。

方案3:手动构造匿名对象(临时解决方案)

如果不想改序列化配置,也可以在插入前将Dictionary转为字符串键的字典:

var formattedDict = foo.dictionary.ToDictionary(pair => pair.Key.ToString(), pair => pair.Value);

之后把这个新的Dictionary<string, int>赋值给要插入的对象属性即可。

你之前尝试ExpandoObject没有生效是因为默认序列化器仍然会把实现了IDictionary<int, T>的对象按键值对数组处理,只要你手动把int键转成字符串再存到ExpandoObject中也能实现效果,但是没有上面的方案高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:54:05