C#将byte[]解析为json而不将其转换为base64字符串

4
我想将我的模型转换为json,它有一个byte[]数组,在转换为json时会将其转换为base64字符串。我不想将byte[]数组转换为字符串格式。
这是我尝试过的:
       MyModel myObject = new MyModel
        {
            Id = 1,                
            Data = new byte[] { 0x01, 0x02, 0x03 }
        };
        string json = JsonSerializer.Serialize(myObject, options);

它将输出返回为 Json string output

我想要的输出是{"Id":[1],"Data":[1,2,3]}

编辑: 我有一个PowerShell脚本的代码可以实现相同的功能

$CertificateJsonString = ConvertTo-Json $CertificateVaultObject -Compress
$CertificateSecureString = ConvertTo-SecureString -String $CertificateJsonString -AsPlainTextForce

2
所以你得到了“AQID”,并期望得到1、2、3。这怎么可能呢?你确定你正在查看你发布的代码的输出吗?你运行了旧版本吗?为什么ID应该是一个数组([1]),当它只是一个int - Thomas Weller
1
不知道是否为一种干净的方法,但或许可以使用一个带有数据 int[] 的中间类,序列化应该生成像请求输出的 int 数组这样的输出。 - Arnaud
3
还有,您认为 Id = 1 应该得到 "Id":[1] 而不是 "Id":1?这似乎是一个完全不同的要求。 - dbc
1
我有证书字节数据,我想将其仅以byte[]格式存储在某个地方,然后您必须将其序列化为BASE64。当进行反序列化时,您将获得原始缓冲区。 - Panagiotis Kanavos
3
将二进制内容编码为BASE64是标准的一部分。使用自己的自定义序列化格式将使与任何其他应用程序(包括您自己的应用程序)的协作变得更加困难,因为您必须在各个地方重复定制。 - Panagiotis Kanavos
显示剩余4条评论
1个回答

9

System.Text.Json(和Json.NET)仅在将 字节数组 序列化为Base64时使用,因此,如果您将Data声明为其他的字节集合或可枚举对象(但不是object),它将被序列化为一个JSON数组,例如:

public class MyModel
{
    public int Id { get; set; }
    public IEnumerable<byte>? Data { get; set; }
}

当通过序列化时:

MyModel myObject = new MyModel
{
    Id = 1,                
    Data = new byte[] { 0x01, 0x02, 0x03 }
};
string json = JsonSerializer.Serialize(myObject, options);

结果为:

{"Id":1,"Data":[1,2,3]}

演示fiddle #1 这里

或者,如果您不能更改您的模型,您可以引入一个JsonConverter<byte>,将byte []值往返地转换为数组:

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

并且可以这样序列化:

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

并获得相同的结果。

演示fiddle #2 在这里

注:


如果该有效载荷是证书数据,则除了BASE64以外的任何内容都可能会出问题。 - Panagiotis Kanavos
@PanagiotisKanavos - 这似乎是一个奇怪的要求,但有时确实会出现。等价的问题Json.NET 如何将byte[]序列化为简单的JSON数组而不是在JSON.net中作为base64?已经获得了31个投票,因此我认为这也是System.Text.Json的一个合法问题。 - dbc
@PanagiotisKanavos 为什么? - Mike Nakis
2
@MikeNakis 首先,这违反了标准(https://datatracker.ietf.org/doc/html/rfc7493#section-4.4),这意味着其他应用程序将难以处理该非标准字段。标准推荐使用BASE64的原因是否则数据类型会丢失。由于JSON没有明确的数字类型,那个*数字*列表可以被翻译成任何东西,包括浮点数。假设您知道存储在该字段中的内容,就不可能误译BASE64。一系列数字需要更多的空间。 - Panagiotis Kanavos
@PanagiotisKanavos - 我添加了一条注释,提到了您的评论,链接到标准,并建议直接使用Base64。 - dbc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接