将属性从byte[]改为List<byte[]>时JSON序列化器报500错误如何解决?
Base64图片列表反序列化失败导致500错误
问题背景
通过纯JSON上传Base64编码图片,属性类型为byte[]时运行正常,但改为List<byte[]>以支持多文件上传后,出现500错误:
System.Private.CoreLib: Unable to cast object of type 'System.Byte[]' to type 'System.Collections.Generic.List`1[System.Byte[]]'
现有代码
原Json转换器
public class Base64FileJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(string); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader?.Value == null) return Array.Empty<byte>(); return Convert.FromBase64String(reader.Value as string); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new InvalidOperationException("Read only converter"); } }
模型属性定义
[ApiBodyParameter( IsOptional = true, Description = "List/array of BASE64 encoded image data for the item images" )] [JsonConverter(typeof(Base64FileJsonConverter))] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<byte[]> ResellImageBase64Data { get; set; }
尝试修改的失败代码
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader?.Value == null) return Array.Empty<byte>(); var returnList = new List<byte[]>(); foreach (var image in reader.ReadAsBytes()) { var jongel = Convert.FromBase64String(image.ToString()); returnList.Add(jongel); } return returnList; }
问题原因
- 原转换器仅能处理单个字符串转byte[],但现在要处理的是字符串数组转List<byte[]>,
CanConvert的判断逻辑完全不匹配当前属性类型。 - 将转换器直接挂在
List<byte[]>属性上后,转换器仍返回单个byte[]实例,导致框架尝试将byte[]强制转换为List<byte[]>,触发类型转换异常。
解决方案
方案一:复用原转换器(推荐)
调整转换器的CanConvert逻辑,让它负责处理单个byte[]的反序列化,JSON.NET会自动处理数组到列表的转换:
- 修改转换器:
public class Base64FileJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { // 改为支持byte[]类型 return objectType == typeof(byte[]); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader?.Value == null) return Array.Empty<byte>(); return Convert.FromBase64String(reader.Value as string); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new InvalidOperationException("Read only converter"); } }
- 移除模型属性上的转换器(JSON.NET会自动遍历数组元素并应用转换器):
[ApiBodyParameter( IsOptional = true, Description = "List/array of BASE64 encoded image data for the item images" )] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<byte[]> ResellImageBase64Data { get; set; }
方案二:编写支持列表的转换器
如果需要自定义列表级别的处理(比如空值兼容、特殊格式校验),可以编写专门处理List<byte[]>的转换器:
public class Base64FileListJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(List<byte[]>) || objectType == typeof(byte[]); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 处理空值 if (reader.TokenType == JsonToken.Null) { return objectType == typeof(List<byte[]>) ? new List<byte[]>() : Array.Empty<byte>(); } // 处理单个Base64字符串(兼容旧格式) if (reader.TokenType == JsonToken.String) { var bytes = Convert.FromBase64String(reader.Value as string); return objectType == typeof(List<byte[]>) ? new List<byte[]> { bytes } : bytes; } // 处理Base64字符串数组 if (reader.TokenType == JsonToken.StartArray) { var imageList = new List<byte[]>(); while (reader.Read()) { if (reader.TokenType == JsonToken.EndArray) break; if (reader.TokenType == JsonToken.String) { imageList.Add(Convert.FromBase64String(reader.Value as string)); } } return imageList; } throw new JsonSerializationException("无效的Base64图片数据格式"); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new InvalidOperationException("Read only converter"); } }
然后在模型属性上使用这个新转换器:
[ApiBodyParameter( IsOptional = true, Description = "List/array of BASE64 encoded image data for the item images" )] [JsonConverter(typeof(Base64FileListJsonConverter))] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public List<byte[]> ResellImageBase64Data { get; set; }
内容的提问来源于stack exchange,提问作者Matt Douhan
相关产品推荐
相关产品推荐

