3

I have an object with a number of public properties where one is of type image. I am trying to serialise this using json.net and assume that I will need to base64 encode this and serialise the resultant string. I have tried with the BinaryConverter against the property without success below

public class Person
{
    public string name { get; set; }

    public int age { get; set; }

    [JsonConverter(typeof(BinaryConverter))]
    public Image photo { get; set; }

    public string ToJson()
    {
        return JsonConvert.SerializeObject(this);
    }
}

When called with this test code...

var p = new Person();
p.name = "John Doe";
p.age = 99;
p.photo = Image.FromFile(@"dea4007a-c812-41e9-b09a-c7793c6e853d.jpg");

var json = p.ToJson();
Console.WriteLine(json);
Console.ReadKey();

I get an exception "Unexpected value type when writing binary". Any help would be very helpful as I have been searching the web for a while now without success.

2
  • 2
    wouldn't be better to return a link to the image? Commented Jun 5, 2017 at 13:28
  • No. There's various cases where the json doesn't represent a request sent back to a web page or a resource otherwise available, but an object transferred between systems, for example for synchronization purposes. Commented Mar 22, 2019 at 17:21

3 Answers 3

15

Json.NET has no idea about what is Image, so you have to help it a bit, for example by using a converter (BinaryConverter is not for images):

public class ImageConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        var base64 = (string)reader.Value;
        // convert base64 to byte array, put that into memory stream and feed to image
        return Image.FromStream(new MemoryStream(Convert.FromBase64String(base64)));
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        var image = (Image) value;
        // save to memory stream in original format
        var ms = new MemoryStream();
        image.Save(ms, image.RawFormat);
        byte[] imageBytes = ms.ToArray();
        // write byte array, will be converted to base64 by JSON.NET
        writer.WriteValue(imageBytes);
    }

    public override bool CanConvert(Type objectType) {
        return objectType == typeof(Image);
    }
}

public class Person
{
    public string name { get; set; }

    public int age { get; set; }

    [JsonConverter(typeof(ImageConverter))]
    public Image photo { get; set; }

    public string ToJson()
    {
        return JsonConvert.SerializeObject(this);
    }
}

Then it will both serialize and deserialize your class just fine.

Sign up to request clarification or add additional context in comments.

Comments

4

I would recommend in this case to convert the image to base64 and then serialize it, here an example of how to do it in C#: Convert Image to Base64

Comments

0

Construct a JSONConverter class as follows:

public class ImageJsonConverter
        : JsonConverter<Image>
    {

        public override void WriteJson(JsonWriter writer, Image value, JsonSerializer serializer)
        {
            if (value == null)
            {
                writer.WriteNull();
                return;
            }

            // Save to memory stream in original format.
            using (MemoryStream ms = new MemoryStream())
            {
                Image image = value;
                image.Save(ms, image.RawFormat);
                byte[] imageBytes = ms.ToArray();

                // Write byte array, will be converted to base64 by JSON.NET.
                writer.WriteValue(imageBytes);
            }
        }
        public override Image ReadJson(JsonReader reader, Type objectType, Image existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String)
            {
                string base64 = reader.Value?.ToString();
                if (string.IsNullOrEmpty(base64))
                {
                    return null;
                }

                // Convert base64 to byte array,
                // put that into memory stream and feed to image.
                return Image.FromStream(new MemoryStream(Convert.FromBase64String(base64)));
            }
            return null;
        }

    }

Then use the JsonConverterAttribute to specify that a JsonConverter should be used when serializing and deserializing a property.

public class Person
{
    public string name { get; set; }
    public int age { get; set; }

    [JsonConverter(typeof(ImageJsonConverter))]
    public Image photo { get; set; }

    public string ToJson()
    {
        return JsonConvert.SerializeObject(this);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.