为什么 jackson 在转换为 json 时将字节数组转换为 base64 字符串?

问题描述

当我在 DTO 中有一个字节数组并使用 jackson 的 ObjectMapper 将其转换为 json 时,它会自动将字节数组转换为 base64 字符串。示例如下。

@Data
@AllArgsConstructor
class TestDTO {
    private byte[] binaryFile;
}

class TestByteSerialization {
    public static void main(String[] args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = Files.readAllBytes(new File("path/to/file/test.pdf").toPath());

        TestDTO dto = new TestDTO(bytes);

        String json = objectMapper.writeValueAsstring(dto);
        System.out.println(json);
    }
}

我希望 jackson 将其转换为如下所示的整数数组:

{
    "binaryFile" : [21,45,12,65,37,etc]    
}

但相反,我发现它被转换为 base64 字符串。经过一番研究,似乎json不支持here中提到的字节数组。

但我仍然找不到为什么json不支持字节数组的答案?它仍然只是一个数字数组,对吗?需要将其转换为 base64 编码的字符串吗?将字节数组按原样传递给 json 字符串作为数字数组有什么问题?

解决方法

将字节数组按原样传递给 json 字符串作为数字数组有什么问题?

没什么,如果您对每个输入字节(平均,假设字节分布均匀)3.57 个字符感到满意。那是假设你不要在每个逗号后面有一个空格 - 否则它是 4.57 个字符。

因此将这些数据大小与 10K 数据进行比较:

  • 原始:10240 字节(不能直接用 JSON 表示)
  • Base64:13656 个字符
  • 数字数组:36556 个字符

base64 增加 33% 的大小已经够痛苦了……使用数组的大小增加要糟糕得多。所以约定是改用base64。 (这只是一个约定 - 它并没有融入 JSON 规范。但大多数 JSON 编码器和解码器都遵循它。)