如何在反序列化前处理JSON,将逗号分隔字符串转为int集合?
解决逗号分隔字符串转整数集合的反序列化问题
当然可以!这种JSON字段类型和目标模型类型不匹配的场景很常见,咱们可以通过自定义序列化转换器来搞定,下面分两种主流的.NET序列化库给出具体实现:
方案一:使用Newtonsoft.Json(Json.NET)
Newtonsoft.Json的扩展性很强,写个自定义转换器就能轻松处理这种字符串转集合的需求:
1. 实现自定义转换器
public class StringToIntCollectionConverter : JsonConverter<ICollection<int>> { public override ICollection<int> ReadJson(JsonReader reader, Type objectType, ICollection<int> existingValue, bool hasExistingValue, JsonSerializer serializer) { // 读取JSON中的字符串值 var rawValue = reader.Value?.ToString(); if (string.IsNullOrWhiteSpace(rawValue)) { return new List<int>(); } // 分割字符串、转整数,同时处理可能的空格和无效值 return rawValue.Split(',') .Select(item => int.TryParse(item.Trim(), out int num) ? num : -1) .Where(num => num != -1) // 过滤转换失败的项,你也可以改成抛出异常 .ToList(); } public override void WriteJson(JsonWriter writer, ICollection<int> value, JsonSerializer serializer) { // 如果需要把模型序列回JSON,这里负责把集合转成逗号分隔字符串 writer.WriteValue(string.Join(",", value)); } }
2. 在模型上标记转换器
给Target属性加上转换器标记,告诉序列化库用咱们写的逻辑处理这个字段:
public class YourModel { public string Description { get; set; } [JsonConverter(typeof(StringToIntCollectionConverter))] public ICollection<int> Target { get; set; } // 注意:JSON里的Category字段有个尾空格,这里要加上JsonProperty标记匹配 [JsonProperty("Category ")] public int Category { get; set; } }
3. 执行反序列化
string json = "{\"url_service\": \"\", \"Description\": null, \"Target\": \"5,6\", \"Category \": \"2\"}"; var model = JsonConvert.DeserializeObject<YourModel>(json); // 此时model.Target就是包含5和6的List<int>啦
方案二:使用System.Text.Json(.NET Core/.NET 5+内置)
如果用的是.NET Core或更高版本的内置序列化库,同样可以自定义转换器:
1. 实现自定义转换器
public class StringToIntCollectionConverter : JsonConverter<ICollection<int>> { public override ICollection<int> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var rawValue = reader.GetString(); if (string.IsNullOrWhiteSpace(rawValue)) { return new List<int>(); } return rawValue.Split(',') .Select(item => int.TryParse(item.Trim(), out int num) ? num : -1) .Where(num => num != -1) .ToList(); } public override void Write(Utf8JsonWriter writer, ICollection<int> value, JsonSerializerOptions options) { writer.WriteStringValue(string.Join(",", value)); } }
2. 应用转换器
有两种方式可以让序列化库使用这个转换器:
方式A:全局配置序列化选项
var serializeOptions = new JsonSerializerOptions(); serializeOptions.Converters.Add(new StringToIntCollectionConverter()); // 同样要处理Category字段的尾空格问题 serializeOptions.PropertyNameCaseInsensitive = true; // 或者给模型加JsonPropertyName标记 string json = "{\"url_service\": \"\", \"Description\": null, \"Target\": \"5,6\", \"Category \": \"2\"}"; var model = JsonSerializer.Deserialize<YourModel>(json, serializeOptions);
方式B:直接在模型属性上标记
public class YourModel { public string Description { get; set; } [JsonConverter(typeof(StringToIntCollectionConverter))] public ICollection<int> Target { get; set; } [JsonPropertyName("Category ")] public int Category { get; set; } }
额外提醒
- 别忘了处理JSON里
Category字段的尾空格!如果不匹配,反序列化后Category会是默认值0,上面的代码里已经给出了两种解决方式。 - 转换器里的
int.TryParse是为了容错,如果JSON里出现非数字的项,会转成-1然后过滤掉,你可以根据自己的需求调整——比如改成抛出异常,或者保留无效值。
内容的提问来源于stack exchange,提问作者Haggui Ayoub
相关产品推荐
相关产品推荐

