Json序列化和Jdk序列化在存储上的对比?

Json序列化和Jdk序列化在存储、效率上的对比?
在之前学习Redis时,我了解的是Json序列化比原生Jdk更高效,占用空间更小,所以无脑选择Json序列化。

但是最近我在看Pig开源框架中Oauth2的时候,发现存入Token令牌居然是用的Jdk序列化方式,我很疑惑,于是自己再用Json的方式去存,看看到底会有什么区别。
结果发现Json方式占用空间比Jdk的大了很多(Jdk为17)。
image.png
image.png

我又尝试别的数据,分别用Json和jdk试试,这里Json序列化占用内存更小,为什么会出现这样的情况?
image.png
image.png
以下是测试的方法:

@SpringBootTest
public class RedisSerializerTest {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    ObjectMapper objectMapper;
    @BeforeEach
    void initRedisTemplate() {
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(genericJackson2JsonRedisSerializer());
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer());
    }

    @BeforeEach
    void initObjectMapper() {
        objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
    }

@Test
    void testRedis() throws JsonProcessingException {
        ComplexObject complexObject = createComplexObject();
        redisTemplate.opsForValue().set("testSerailizerByJson:1",complexObject );
        redisTemplate.setValueSerializer(RedisSerializer.java());
        redisTemplate.opsForValue().set("testSeralizerByJdk:1", complexObject);


    }

 ComplexObject createComplexObject()  {
        ComplexObject complexObject = new ComplexObject();
        complexObject.setName("Test Name");
        complexObject.setAge(30);
        complexObject.setHobbies(Arrays.asList("Hobby1", "Hobby2", "Hobby3"));
        Map<String, String> attributes = new HashMap<>();
        for (int i = 0; i < 1000; i++) {
            attributes.put("Attribute" + i, "Value" + i);
        }
        complexObject.setAttributes(attributes);
        complexObject.setLargeString("This is a large string to increase the size of the object...");
        return complexObject;
    }
阅读 1.5k
3 个回答

JSON

基于字符,于是非字符的东西占用空间更多,比如数字,比如二进制,比如 bool
因为是字符所以可读,可编辑
另外是一种语言无关的格式,啥程序都能读

JDK 序列化

相比于其他二进制序列化,存了类型等等一些额外的东西,所以也没高效多少,但是因为是二进制的,所以存二进制数据相对更省空间
但是这玩意只有 Java程序可以读,而且只能程序读,直接看数据基本看不明白是啥,更不用说修改

我自己测试了一下,测试代码:

public class Test {
@Data
static class Person implements Serializable {
    private String name;
    private int age;
    private List<String> hobbies;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

    public static void main(String[] args) throws IOException {
        // 创建一个示例Person对象
        Person person = new Person("cc", 22);
        List<String> hobbies = new ArrayList<>();
        for (int i = 0; i < 10000000; i++) {
            hobbies.add("hobby" + i);
        }
        person.setHobbies(hobbies);
        // 使用Java原生序列化
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(person);
        oos.close();
        byte[] nativeSerialized = baos.toByteArray();
        System.out.println("JDK size: " + nativeSerialized.length + " bytes");

        // 使用Jackson进行JSON序列化
        ObjectMapper mapper = new ObjectMapper();
        String  jsonString  = mapper.writeValueAsString(person);
        // 假设JSON字符串编码为UTF-8
        byte[] jsonSerialized = jsonString.getBytes("UTF-8");
        System.out.println("JSON size: " + jsonSerialized.length + " bytes");
    }}

测出来后面i在千级别,两个相差就不太明显了

实际使用的话,更加推荐用JSON,如果允许,更推荐Protobuf,非要说区别的话,假设数据量大

JSON序列化:可读,易编辑,跨平台,可拓展,可选择存储类型信息,但需要的存储空间很大,对象非常大时,对序列化框架要求很高,容易堆内存溢出,且耗时长,并且存在循环引用问题,且存储类型后,全限定名修改会引发异常。

JDK序列化: 仅Java程序可读,自带类型定义,类修改后可控制版本,在数据量很大时,性能极强,更节省存储空间,网络传输更快,反序列化更快,只要Java对象能定义,就能存储,Java层面兼容性很强

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏