System.Text.Json (and Json.NET) only serializes byte arrays as Base64, so if you declare your Data as some other collection or enumerable of bytes (but not object) it will be serialized as a JSON array, e.g:
public class MyModel
{
public int Id { get; set; }
public IEnumerable<byte>? Data { get; set; }
}
When serialized via:
MyModel myObject = new MyModel
{
Id = 1,
Data = new byte[] { 0x01, 0x02, 0x03 }
};
string json = JsonSerializer.Serialize(myObject, options);
Results in:
{"Id":1,"Data":[1,2,3]}
Demo fiddle #1 here.
Or, if you can't change your model, you could introduce a JsonConverter<byte> that round-trips byte [] values as an array:
public class ByteArrayConverter : JsonConverter<byte []>
{
public override void Write(Utf8JsonWriter writer, byte [] value, JsonSerializerOptions options) =>
JsonSerializer.Serialize(writer, value.AsEnumerable());
public override byte []? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
reader.TokenType switch
{
JsonTokenType.String => reader.GetBytesFromBase64(),
JsonTokenType.StartArray => JsonSerializer.Deserialize<List<byte>>(ref reader)!.ToArray(),
JsonTokenType.Null => null,
_ => throw new JsonException(),
};
}
And serialize like so:
MyModel myObject = new MyModel
{
Id = 1,
Data = new byte[] { 0x01, 0x02, 0x03 }
};
var options = new JsonSerializerOptions { Converters = { new ByteArrayConverter() } };
string json = JsonSerializer.Serialize(myObject, options);
And get the same result.
Demo fiddle #2 here.
Notes:
[1]) when it's only anint?Id = 1should result in"Id":[1]not"Id":1? That seems to be a completely different requirement.