fastJson、JackJson以及Gson序列化对象与get、set以及对象属性之间的关系

本文详细探讨了fastJson、Gson、Jackson三种JSON序列化工具的实现原理,特别是在处理对象属性、get和set方法时的区别。揭示了Gson通过反射遍历属性,而Jackson和fastJson依赖getter方法的特点。

       众所周知,平时开发过程中将对象序列化成json字符串常用的工具类一般就三种:fastJson、Gson、Jackjson,但是三种工具类在将对象进行序列化时与对象的get、set、对象属性之间的关系你知道吗,如果知道了,那么下面的你没必要看了,不知道的话请继续看下去。

1.与对象属性之间的关系

       为了区分三者之间的关系,我创建了一个测试类,只有一个success属性,没有get、set方法,默认值为false,可以看出,gson的序列化结果是{"success":false},fastJson的结果是{},jackJson直接报错,由此可以得出结论:Gson是通过反射遍历该类中的所有属性,并把其值序列化成json,至于FastJson和JackJson的序列化跟属性暂时看不出来关系。

2.与对象的set方法之间的关系

       为了测试跟set方法的关系,我在测试类中给该属性加了一个set方法,运行的结果显示跟上面的一样,可以猜想跟set方法没关系,但是有的人可能会说,有可能通过反射遍历出该类中的所有setter方法,得到setSuccess,然后根据JavaBeans规则,获取测试类的属性,然后序列化成json,跟直接通过属性序列化的结果一样,因此只展示一个。因此我又在测试类中加了一个setTestSuccess方法,结果如下:

 

      运行的结果显示跟上面的一样,并没有多出任何结果,因此得出结论:三个工具类的序列化结果跟类的set方法没有关系。

3.与对象的get方法之间的关系

       为了测试与get方法的关系,我加上了success属性的get方法,有人可能会说,不应该是getSuccess(),怎么是isSuccess()方法,具体原因请看我的博客《关于boolean类型的数据不推荐使用isXXX命名的那些事》,这里大致说一声,boolean类型的数据,其get方法默认就是isXXX(),不是getXXX(),这是规定的。

       从结果可以出,Gson序列化后的结果不变,而JackJson和FastJson不再报错,而是出现了结果,跟Gson序列化的结果一样,因此可以猜想JackJson和FastJson序列化结果跟get方法有关系,而Gson序列化的结果跟get方法有没有关系还不确定。因此我们还得再加一个get方法和一个isXXX()方法来测试,测试结果如下:

       我在测试类中又加了一个isSuccessSecond()和getAuthorName(),结果发现gson序列化的结果还是不变的,但是jackJson和fastJson序列化的结果中多了两个值authorName和successSecond。

      因此可以得出结论:fastjson和jackson在把对象序列化成json字符串的时候,是通过反射遍历出该类中的所有getter方法,得到getAuthorName和isSuccessSecond,然后根据JavaBeans规则,他会认为这是两个属性authorName和successSecond的值,直接序列化成json。

综上所述:Gson是通过反射遍历该类中的所有属性,并把其值序列化成json字符串;JackJson和fastJson是通过getter方法获取属性,并把其值序列化成json字符串。

       三者的序列化都跟setter()没有任何关系,至于单个测试属性,setter方法、getter方法,我都试过,这里就不一一贴出来代码,想测试的大兄弟们可以自己测试,若有问题,请及时反馈。可能有人说跟isXXX()有关,其实是跟get方法有关,主要是boolean类型的属性,其get方法默认都是isXXX,Boolean类型的属性,其get方法还是getXXX(),感兴趣的同学可以看一下我的博客《关于boolean类型的数据不推荐使用isXXX命名的那些事》。如果还是认为跟isXXX()有关,可以自己试一下其它类型的属性。

 

 

在使用 Redis 进行缓存时,对象序列化和反序列化是实现数据持久化和传输的关键步骤。Redis 本身存储的是字节流,因此需要将对象转换为可存储和传输的格式。以下介绍几种常见的方法及其实现方式。 ### 使用 JSON 序列化 JSON 是一种常用的数据交换格式,它具有可读性强、跨语言支持好等优点。常见的 JSON 序列化库包括 JacksonGsonFastjson。 以 Jackson 为例,可以通过自定义 `RedisTemplate` 的序列化方式来实现: ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); template.afterPropertiesSet(); return template; } } ``` 这种方式将对象序列化为 JSON 格式,并在反序列化时恢复为原始对象,适用于大多数场景[^2]。 ### 使用 Protobuf 序列化 Protocol Buffers(Protobuf)是由 Google 开发的一种高效、紧凑的序列化方式,适用于对性能和存储空有较高要求的场景。Protobuf 需要预先定义数据结构(.proto 文件),然后通过工具生成代码进行序列化和反序列化。 以下是一个简单的 Protobuf 序列化示例: ```java // 定义 .proto 文件 syntax = "proto3"; message User { string name = 1; int32 age = 2; } // 序列化 User user = User.newBuilder().setName("Alice").setAge(30).build(); byte[] data = user.toByteArray(); // 反序列化 User parsedUser = User.parseFrom(data); ``` 将 Protobuf Redis 结合使用时,可以将 `RedisTemplate` 的序列化器替换为自定义的 Protobuf 序列化器,从而实现高效的数据存储和读取。 ### 使用 Kryo 序列化 Kryo 是一个高效的 Java 序列化框架,支持循环引用、压缩等特性。Kryo 的序列化速度和压缩率优于 JDK 自带的序列化方式,但其生成的字节流不具备可读性。 可以通过以下方式配置 Kryo 序列化: ```java public class KryoRedisSerializer<T> implements RedisSerializer<T> { private final Class<T> type; private final Kryo kryo = new Kryo(); public KryoRedisSerializer(Class<T> type) { this.type = type; } @Override public byte[] serialize(T t) { Output output = new Output(1024, -1); kryo.writeObject(output, t); return output.toBytes(); } @Override public T deserialize(byte[] bytes) { if (bytes == null) { return null; } Input input = new Input(bytes); return kryo.readObject(input, type); } } ``` 配置 `RedisTemplate` 使用 Kryo 序列化器: ```java @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new KryoRedisSerializer<>(MyObject.class)); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(new KryoRedisSerializer<>(MyObject.class)); template.afterPropertiesSet(); return template; } ``` ### 使用 Avro 序列化 Apache Avro 是另一个流行的序列化框架,支持模式演化(Schema Evolution),适用于需要长期存储和兼容性要求的场景。Avro 支持多种序列化格式,包括二进制和 JSON。 Avro 的使用需要定义 `.avsc` 文件,然后通过工具生成对应的 Java 类。以下是 Avro 的基本使用方式: ```java // 序列化 User user = new User("Alice", 30); ByteArrayOutputStream out = new ByteArrayOutputStream(); DatumWriter<User> writer = new SpecificDatumWriter<>(User.class); Encoder encoder = EncoderFactory.get().binaryEncoder(out, null); writer.write(user, encoder); encoder.flush(); byte[] data = out.toByteArray(); // 反序列化 DatumReader<User> reader = new SpecificDatumReader<>(User.class); Decoder decoder = DecoderFactory.get().binaryDecoder(data, null); User parsedUser = reader.read(null, decoder); ``` 将 Avro Redis 结合使用时,可以将 `RedisTemplate` 的序列化器替换为 Avro 序列化器,从而实现结构化数据的高效存储。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值