Newtonsoft.Json deserializing base64 image fails

前端 未结 3 1263
甜味超标
甜味超标 2020-12-09 23:18

I\'m using Newtonsoft.Json to deserialize the output from my webservice to an object. It worked fine until I added a Bitmapproperty to my class (named Use

相关标签:
3条回答
  • 2020-12-09 23:28

    This is my solution, I used the annotation

    [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
    
    0 讨论(0)
  • 2020-12-09 23:42

    Read that field as string,

    convert to byte array using Convert.FromBase64String and

    get the image using Bitmap.FromStream(new MemoryStream(bytearray));

    EDIT

    You can perform image serialization/deserialization with the help of a custom converter

    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());
    

    This is the 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()));
        }
    }
    
    0 讨论(0)
  • 2020-12-09 23:45

    I think that the Deserializing from Base64 to System.Drawing.Bitmap is not supported. May be you can try deserializing everything excepts the Avatar property

    EDIT FOR EDITED QUESTION

    Here is an interesting discussion on how to do that: JSON.Net Ignore Property during deserialization

    I think the best that you can do is use Regex to remove the property from the json string:

    var newJsonString = Regex.Replace(jsonString, 
                                      "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"", 
                                      String.Empty);
    

    and then deserialize this newJsonString without the Avatar property.

    Later you can parse the original json string to get the base64 and build the Bitmap

    var avatarBase64 = Regex.Match(
                            Regex.Match(json, "(\\,)* \"Avatar\": \"[A-Za-z0-9]+\"")
                                 .ToString(), 
                            "[A-Za-z0-9]+", RegexOptions.RightToLeft)
                            .ToString();
    
    ...
    
    byte[] fromBase64 = Convert.FromBase64String(avatarBase64);
    using (MemoryStream ms = new MemoryStream(fromBase64))
    {
        Bitmap img = (Bitmap)Image.FromStream(ms);
        result.Avatar = img;
    }
    

    You could improve the regular expressions or the method, but that's the basic idea.

    0 讨论(0)
提交回复
热议问题