51

I have a simple class with the following property:

[JsonObject(MemberSerialization.OptIn)]
public class Person
{
    ...
    [JsonProperty(PropertyName = "Photograph"]
    public byte[] Photograph { get; set; }
    ...
}

but this doesn't work when I populate the Photograph property with an image and transfer over http. This may sound like a simple question but I've yet to find a solution after looking online for hours, but, how do I serialise/deserialise a byte array in Json.NET? What attribute tags do I need, or, should I be doing this another way? Many thanks!

4
  • 4
    Have you found a way to set the correct object's properties? The information is somewhat fragmented. I'm looking for a clean solution for the exact same problem. the byte[] should be converted to an array, not a string. Commented Feb 26, 2013 at 7:19
  • 1
    I think JSON.NET has issues with fixed-length arrays when you preserve references and type information. When preserving type names in the "$type" member, it throws an error while trying to deserialize a fixed-length or read-only array. You have to use List<T> instead, or use a JsonConverter to serialize the byte[] member. It really needs to be fixed, because it should not have issues with such basic things. Commented Dec 3, 2013 at 20:36
  • 4
    Maybe you can use Base64 : Convert.ToBase64String(File.ReadAllBytes(downloadPth) and Convert.FromBase64String(b64Str) Commented Oct 2, 2018 at 4:31
  • Convert.ToBase64String worked for me! also ascii or utf8 are too small for store images data Commented Oct 10, 2022 at 12:08

4 Answers 4

40
public static T Deserialize<T>(byte[] data) where T : class
{
    using (var stream = new MemoryStream(data))
    using (var reader = new StreamReader(stream, Encoding.UTF8))
        return JsonSerializer.Create().Deserialize(reader, typeof(T)) as T;
}
Sign up to request clarification or add additional context in comments.

5 Comments

I like this answer, but you may want to throw an Encoding.UTF8 argument into the second argument of the StreamReader constructor. I am always a bit leery about using the default encoding.
Updated the snippet to have Encoding.UTF8
Notice this answer is >2 years old. I'm not sure when the System.Text.Json namespace was added, but JsonSerializer doesn't have a Create method.
System.Text.Json is a part of .NET Core 3, which was made GA one month ago
Plus, the method mentioned is from Newtonsoft.Json
32

You can convert the byte[] into a string then use the JsonConvert method to get the object:

var bytesAsString = Encoding.UTF8.GetString(bytes);
var person = JsonConvert.DeserializeObject<Person>(bytesAsString);

4 Comments

Be wary of using this method for large objects as you will get OutOfMemory Exceptions. Methods that use Stream(s) would be better equipped to handle OutOfMemory scenarios.
There are a few standards that use ASCII. JSON is not one of them. It uses UTF-8 (or, older standard, UTF-8, UTF-16, or UTF-32—all easily distinguished, given that the data is JSON syntax).
@TomBlodget I have updated my answer to reflect your suggestions.
If you have "random" byte from photography, I think that you will get exceptions sometime: T:System.ArgumentException: The byte array contains invalid Unicode code points. In the documentation of Json.NET it is declared that a Byte[] will be serialized as a Base64 encoded string.
8

If you are using LINQ to JSON, you can do this:

JObject.Parse(Encoding.UTF8.GetString(data));

The result will be a dynamic JObject.

While this might not be exactly what the OP was looking to do, it might come in handy for others looking to deserialize a byte[] that come across this question.

Comments

1

Based on this answer, you could use the one below in net core:

using System.IO;
using System.Text.Json;
using System.Threading.Tasks;

namespace <MyNameSpace>
{
    public static class ByteArrayExtensions
    {
        public static async Task<T> Deserialize<T>(this byte[] data) where T : class
        {
            using (var stream = new MemoryStream(data))
            {
                return await JsonSerializer.DeserializeAsync(stream, typeof(T)) as T;
            }
        }
    }
}

Which may be considered to have the edge on readability:

var deserialized = await mySerializedByteArray.Deserialize<MyObjectClass>();

1 Comment

In STJ version 6, this can be collapsed to JsonSerializer.Deseralize<T> (I assume there is an Async variant too) - the byte[] gets implictly converted to fit. static TValue? Deserialize<TValue>(ReadOnlySpan<byte> utf8Json, JsonSerializerOptions? options = null)

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.