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

使用JsonConvert.SerializeObject将列表转字典时如何保留int类型键?

解决JsonConvert序列化字典时int类型Key转为字符串的问题

嘿,这个问题其实是JSON本身的规范限制导致的——JSON对象的键必须是字符串类型,所以默认情况下Json.NET会把int类型的字典Key自动转成字符串。不过我们有几种方式来处理你的需求,看你具体想要什么效果:


方法1:确保反序列化时能正确转回int类型字典

如果你的核心需求只是后续反序列化时能把键变回int,那其实不用做任何额外操作!Json.NET在反序列化的时候会自动识别字符串形式的数字键,并把它们转回int类型的字典Key。比如:

// 序列化后的JSON字符串
var json = "{\"1\": {\"Name\": \"Test\", \"Type\": \"String\"}}";

// 反序列化回Dictionary<int, YourModel>
var dict = JsonConvert.DeserializeObject<Dictionary<int, YourModel>>(json);
// dict的Key会是int类型的1,完全没问题

方法2:自定义转换器,让序列化后的键以数字形式呈现(非严格JSON)

如果你非常希望序列化后的JSON里键看起来是数字(比如{1: {...}}而不是{"1": {...}}),虽然这不符合严格的JSON规范,但可以通过自定义JsonConverter来实现:

public class IntKeyDictionaryConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>) 
               && objectType.GetGenericArguments()[0] == typeof(int);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var dict = (IDictionary)value;
        writer.WriteStartObject();
        foreach (DictionaryEntry entry in dict)
        {
            // 直接把int键作为数字写入,跳过字符串转换
            writer.WritePropertyName(entry.Key.ToString());
            serializer.Serialize(writer, entry.Value);
        }
        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // 反序列化逻辑,确保能把数字键转回int
        var dict = (IDictionary)Activator.CreateInstance(objectType);
        while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
        {
            var key = int.Parse((string)reader.Value);
            reader.Read();
            var value = serializer.Deserialize(reader, objectType.GetGenericArguments()[1]);
            dict.Add(key, value);
        }
        return dict;
    }
}

然后使用这个转换器序列化:

var settings = new JsonSerializerSettings();
settings.Converters.Add(new IntKeyDictionaryConverter());

var jsonString = JsonConvert.SerializeObject(
    this.Fields.Select(f => new { Id = f.Id, Name = f.Name, Type = f.Type })
               .ToDictionary(x => x.Id),
    settings);

⚠️ 注意:这种方式生成的JSON不符合ECMA-404规范,部分严格的JSON解析器可能无法正确处理,所以除非有特殊需求,不推荐这种方式。


方法3:改用数组结构存储(推荐,完全符合JSON规范)

如果你的场景允许调整数据结构,最稳妥的方式是把字典转成包含键值对的数组,这样Id可以保持纯正的int类型:

var jsonString = JsonConvert.SerializeObject(
    this.Fields.Select(f => new { 
        Id = f.Id, 
        Name = f.Name, 
        Type = f.Type 
    }).ToList());

序列化后的JSON会是这样的(Id保持int类型):

[
    {"Id": 1, "Name": "Field1", "Type": "String"},
    {"Id": 2, "Name": "Field2", "Type": "Int"}
]

这种方式完全符合JSON规范,后续处理也更灵活,不会有兼容性问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:59:38