使用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
相关产品推荐
相关产品推荐

