Newtonsoft.Json反序列化base64图像失败

Joe*_*oel 6 .net c# json image

我正在使用Newtonsoft.Json将我的webservice的输出反序列化为一个对象.它工作正常,直到我Bitmap向我的班级(命名User)添加一个属性来持有一个头像.

Web服务将该属性作为Base64字符串返回,这是预期的.问题是当我尝试将JSON从WS转换回a时List<User>,JsonSerializationException会抛出一个代码块:

// T is IList<User>
response.Content.ReadAsStringAsync().Proceed(
    (readTask) =>
    {
        var json = ((Task<string>)readTask).Result;
        var result = JsonConvert.DeserializeObject<T>(json); //<-- it fails here

         // do stuff! 
     });
Run Code Online (Sandbox Code Playgroud)

异常输出是:

Error converting value "System.Drawing.Bitmap" to type 'System.Drawing.Bitmap'. Path '[2].Avatar
Run Code Online (Sandbox Code Playgroud)

并查看内部异常:

{"Could not cast or convert from System.String to System.Drawing.Bitmap."}
Run Code Online (Sandbox Code Playgroud)

很明显,它无法解析Base64字符串,但目前尚不清楚原因.

任何想法/解决方法?

编辑 我知道我可以使用Convert.FromBase64Stringdo得到一个字节数组并从中加载一个位图.然后,我想更新我的问题想请教一下如何我可以跳过或手动解析唯一的那场.我想避免,不得不手动解析所有JSON.这甚至可能吗?

编辑2 我发现了根本问题:在Web服务中没有正确序列化JSON(我不明白为什么).我认为是一个有点不同的问题,但没有.我的webservice只是返回一个字符串"System.Drawing.Bitmap"而不是它的base64内容.因此JsonSerializationException.

我一直无法解决这个问题,我发现的唯一解决方案是将我的领域变成一个byte [].

I4V*_*I4V 10

将该字段读为字符串,

使用Convert.FromBase64String和转换为字节数组

使用获取图像 Bitmap.FromStream(new MemoryStream(bytearray));

编辑

您可以借助自定义转换器执行图像序列化/反序列化

public class AClass
{
    public Bitmap image;
    public int i;
}

Bitmap bmp = (Bitmap)Bitmap.FromFile(@"......");
var json = JsonConvert.SerializeObject(new AClass() { image = bmp, i = 666 }, 
                                       new ImageConverter());

var aclass = JsonConvert.DeserializeObject<AClass>(json, new ImageConverter());
Run Code Online (Sandbox Code Playgroud)

这是 ImageConverter

public class ImageConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Bitmap);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var m = new MemoryStream(Convert.FromBase64String((string)reader.Value));
        return (Bitmap)Bitmap.FromStream(m);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Bitmap bmp = (Bitmap)value;
        MemoryStream m = new MemoryStream();
        bmp.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);

        writer.WriteValue(Convert.ToBase64String(m.ToArray()));
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

这是我的解决方案,我使用了注释

[Serializable]
public class MyClass
{
    [JsonConverter(typeof(CustomBitmapConverter))]
    public Bitmap MyImage { get; set; }


    #region JsonConverterBitmap
    internal class CustomBitmapConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }

        //convert from byte to bitmap (deserialize)

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            string image = (string)reader.Value;

            byte[] byteBuffer = Convert.FromBase64String(image);
            MemoryStream memoryStream = new MemoryStream(byteBuffer);
            memoryStream.Position = 0;

            return (Bitmap)Bitmap.FromStream(memoryStream);
        }

        //convert bitmap to byte (serialize)
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            Bitmap bitmap = (Bitmap)value;

            ImageConverter converter = new ImageConverter();
            writer.WriteValue((byte[])converter.ConvertTo(bitmap, typeof(byte[])));
        }

        public static System.Drawing.Imaging.ImageFormat GetImageFormat(Bitmap bitmap)
        {
            ImageFormat img = bitmap.RawFormat;

            if (img.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
                return System.Drawing.Imaging.ImageFormat.Jpeg;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
                return System.Drawing.Imaging.ImageFormat.Bmp;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Png))
                return System.Drawing.Imaging.ImageFormat.Png;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Emf))
                return System.Drawing.Imaging.ImageFormat.Emf;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Exif))
                return System.Drawing.Imaging.ImageFormat.Exif;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Gif))
                return System.Drawing.Imaging.ImageFormat.Gif;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Icon))
                return System.Drawing.Imaging.ImageFormat.Icon;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
                return System.Drawing.Imaging.ImageFormat.MemoryBmp;
            if (img.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
                return System.Drawing.Imaging.ImageFormat.Tiff;
            else
                return System.Drawing.Imaging.ImageFormat.Wmf;
        }

    }

    #endregion
Run Code Online (Sandbox Code Playgroud)