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

Azure Cosmos DB为何将Dictionary<Object>值存为ValueKind?求解决方案

问题现象

使用C# .NET 8.0及Azure Cosmos DB SDK 3.40.0(NoSQL)定义了如下记录类型:

public record test_rec {
      
    private System.Collections.Generic.Dictionary<String, Object> m_custom;
      
    public System.Collections.Generic.Dictionary<String, Object> custom
    {
        get { return m_custom; }
        set { m_custom = value; }
    }
      
    public test_rec()
    {
        init_members();
    }

    private void init_members()
    {
        m_custom = null;
    }
}

通过custom属性存储键值对的示例代码:

test_rec rec = new test_rec();
rec.custom = new System.Collections.Generic.Dictionary<String,Object>();
rec.custom.Add("key1", null );
rec.custom.Add("key2", "string" );
rec.custom.Add("key3", 100 );

将记录存入Cosmos DB后,在Azure门户查看custom字段的JSON为:

"custom": {
    "key1": null,
    "key2": {
        "ValueKind": 3
    },
    "key3": {
        "ValueKind": 4
    }
}

期望的正确结果应为:

"custom": {
    "key1": null,
    "key2": "string",
    "key3": 100
}
原因解释

这是因为Cosmos DB SDK默认使用的System.Text.Json序列化器,在处理Dictionary<string, object>中的装箱值类型(如int、string等)时,会将其识别为JsonElement的包装对象,进而序列化出ValueKind属性而非原始值。当值类型被装箱为object类型存入字典时,System.Text.Json无法正确解析其原始类型,导致序列化结果不符合预期。

解决方案

方案1:自定义System.Text.Json转换器

通过配置Cosmos客户端的序列化选项,添加自定义转换器来处理object类型的序列化,确保原始值被正确序列化:

// 自定义转换器
public class ObjectValueTypeConverter : JsonConverter<object>
{
    public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return reader.TokenType switch
        {
            JsonTokenType.String => reader.GetString(),
            JsonTokenType.Number => reader.GetInt32(),
            JsonTokenType.True => true,
            JsonTokenType.False => false,
            JsonTokenType.Null => null,
            _ => JsonSerializer.Deserialize(ref reader, typeToConvert, options)
        };
    }

    public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
    {
        if (value == null)
        {
            writer.WriteNullValue();
            return;
        }

        var valueType = value.GetType();
        if (valueType == typeof(string))
        {
            writer.WriteStringValue((string)value);
        }
        else if (valueType == typeof(int))
        {
            writer.WriteNumberValue((int)value);
        }
        else if (valueType == typeof(bool))
        {
            writer.WriteBooleanValue((bool)value);
        }
        // 按需扩展支持更多值类型(如double、long等)
        else
        {
            JsonSerializer.Serialize(writer, value, valueType, options);
        }
    }
}

// 初始化Cosmos客户端时配置序列化选项
var cosmosOptions = new CosmosClientOptions
{
    SerializerOptions = new JsonSerializerOptions
    {
        Converters = { new ObjectValueTypeConverter() }
    }
};
var cosmosClient = new CosmosClient("your-connection-string", cosmosOptions);

方案2:切换到Newtonsoft.Json序列化器

Newtonsoft.Json对object类型的序列化处理更贴合预期,无需自定义转换器即可正确序列化字典中的值类型。

  1. 安装NuGet包:
Install-Package Microsoft.Azure.Cosmos.NewtonsoftJson
  1. 配置Cosmos客户端使用NewtonsoftJson序列化器:
var cosmosOptions = new CosmosClientOptions
{
    Serializer = new NewtonsoftJsonSerializer()
};
var cosmosClient = new CosmosClient("your-connection-string", cosmosOptions);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 09:53:13