Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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 User) to hold an avatar.

The webservice is returning that propert as a Base64 string, which is as expected. The problem is when I try to convert back the JSON from the WS to a List<User>, a JsonSerializationException is thrown in this block of code:

// 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! 
     });

Output from exception is:

Error converting value "System.Drawing.Bitmap" to type 'System.Drawing.Bitmap'. Path '[2].Avatar

and looking at the inner exception:

{"Could not cast or convert from System.String to System.Drawing.Bitmap."}

It's clear that it fails to parse the Base64 string, but it's not clear why.

Any ideas/workaround?

EDIT I know I can use Convert.FromBase64String do get a byte array and load a bitmap from that. Then I'd like to update my question to ask about how can I skip or manually parse only that field. I would like to avoid, having to manually parse all the JSON. Is this even possible?

EDIT 2 I found out the root problem: JSON is not being correctly serialized in webservice (and I fail to see why). I thought that this was a somewhat different issue, but no. My webservice is simply returning a string "System.Drawing.Bitmap" instead of its base64 content. Hence the JsonSerializationException.

I have been unable to solve that issue, the only solution I've found is to turn my field into a byte [].

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
692 views
Welcome To Ask or Share your Answers For Others

1 Answer

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...