Java基础——序列化
- 序列化:把Java对象转换为字节序列。
- 反序列化:把字节序列恢复为原先的Java对象。
序列化方式
Serializable 接口
一个对象想要被序列化,那么它的类就要实现此接口或者它的子接口。
Externalizable 接口
它是Serializable接口的子类,用户要实现的writeExternal()和readExternal() 方法,用来决定如何序列化和反序列化。
因为序列化和反序列化方法需要自己实现,因此可以指定序列化哪些属性,而transient在这里无效。
对Externalizable对象反序列化时,会先调用类的无参构造方法,这是有别于默认反序列方式的。如果把类的不带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出java.io.InvalidException: no valid constructor异常,因此Externalizable对象必须有默认构造函数,而且必需是public的。
不被序列化的情况
- 凡是被static修饰的字段是不会被序列化的
- 凡是被transient修饰符修饰的字段也是不会被序列化的
序列化框架的使用——FastJson
MVC 配置文件 基于Springboot
package com.pengshi.realhole.config;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 开放 静态资源的权限 , 同时配置fastjson
* @projectName: RealHole
* @see: com.pengshi.realhole.config.WebMvcConfig
* @author: pc
* @createTime: 2022/2/11 17:51
* @version: 1.0
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html","doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* 修改自定义消息转化器 配置FastJSON
* @param converters 消息转换器列表
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
/*
先把JackSon的消息转换器删除.
备注: (1)源码分析可知,返回json的过程为:
Controller调用结束后返回一个数据对象,for循环遍历conventers,找到支持application/json的HttpMessageConverter,然后将返回的数据序列化成json。
具体参考org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法
(2)由于是list结构,我们添加的fastjson在最后。因此必须要将jackson的转换器删除,不然会先匹配上jackson,导致没使用fastjson
*/
for (int i = converters.size() - 1; i >= 0; i--) {
if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
converters.remove(i);
}
}
//调用父类的配置
//创建fastJson消息转换器
FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
//创建配置类
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//过滤并修改配置返回内容
fastJsonConfig.setSerializerFeatures(
//List字段如果为null,输出为[],而非null
//SerializerFeature.WriteNullListAsEmpty,
//字符类型字段如果为null,输出为"",而非null
SerializerFeature.WriteNullStringAsEmpty,
//Boolean字段如果为null,输出为falseJ,而非null
//SerializerFeature.WriteNullBooleanAsFalse,
//消除对同一对象循环引用的问题,默认为false(如果不配置有可能会进入死循环)
SerializerFeature.DisableCircularReferenceDetect,
//是否输出值为null的字段,默认为false
SerializerFeature.WriteMapNullValue
);
//处理中文乱码问题
List<MediaType> fastMediaTypes = new ArrayList<MediaType>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastJsonConverter.setSupportedMediaTypes(fastMediaTypes);
fastJsonConverter.setFastJsonConfig(fastJsonConfig);
//将fastjson添加到视图消息转换器列表内
converters.add(fastJsonConverter);
}
}
FastJSON基本使用
package com.pengshi.realhole;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.pengshi.realhole.pojo.User;
import org.junit.jupiter.api.Test;
import java.util.*;
/**
* @description:
* @projectName: RealHole
* @see: com.pengshi.realhole
* @author: pc
* @createTime: 2022/2/13 17:57
* @version: 1.0
*/
public class FastJsonTest {
// java中对象,序列化为json序列化字符串
@Test
public void testObjectJson() {
User user = new User();
user.setId(1);
user.setUsername("pengshi");
user.setPassword("123456");
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);
}
// list集合转为字符串
@Test
public void testListToJson() {
List<User> list = new ArrayList<>();
User user = new User();
user.setId(1);
user.setUsername("pengshi");
user.setPassword("123456");
User user2 = new User();
user2.setId(1);
user2.setUsername("pengshi");
user2.setPassword("123456");
list.add(user);
list.add(user2);
String jsonString = JSON.toJSONString(list);
System.out.println(jsonString);
}
// 将map集合进行json格式转化
@Test
public void testMapToJson() {
Map<String, User> map = new HashMap();
User user = new User();
user.setId(1);
user.setUsername("pengshi");
user.setPassword("123456");
User user2 = new User();
user2.setId(1);
user2.setUsername("pengshi");
user2.setPassword("123456");
map.put("pengshi", user);
map.put("dongye", user2);
String jsonString = JSON.toJSONString(map);
System.out.println(jsonString);
}
// 反序列化操作
@Test
public void testJsonToObject() {
String str = "{\"id\":1,\"username\":\"pengshi\"}";
System.out.println(JSON.parseObject(str, User.class));
}
// 反序列化 为List
@Test
public void testJsonToList() {
String str = "{\"id\":1,\"username\":\"pengshi\"}";
List<User> list = JSON.parseArray(str, User.class);
}
// 反序列化 为Map
public void testJsonToMap() {
String str = "{\"pengshi\":{\"id\":1,\"username\":\"pengshi\"},\"dongye\":{\"id\":1,\"username\":\"pengshi\"}}";
Map map = JSON.parseObject(str, new TypeReference<Map<String, User>>(){}); // 注意这里是一个匿名内部类进行重写
}
// SerializerFeature 枚举 : 进行序列化时,定义自己特殊需求
// JSON静态方法: toJSONString()
// 方法参数1 : 第一个需要序列化的对象
// 方法参数2 : SerializerFeature 枚举类型的可变参数
// SerializerFeature 枚举的常量,做序列化的个性需求
@Test
public void testWriteNullValue() {
// WriteMapNullValue 值为空时候,进行null打印 "email":"null"
// WriteNullStringAsEmpty 值为空时,打印空,只剩下空 "email":""
// WriteNullNumberAsZero 值为空时,打印0,对于number类型而言
User user = new User();
user.setId(1);
user.setUsername("pengshi");
user.setPassword("123456");
String str = JSON.toJSONString(user, SerializerFeature.WriteNullNumberAsZero);
System.out.println(str);
}
// JSONType 注解
// 作用在类上,堆该类的字段进行序列化和反序列化的特性功能定制
// includes 被序列化的字段
// orders 序列化顺序
@JSONType(includes = {"username","date"})
class student {
// @JSONField 注解
// name指定序列化名字
// ordinal 序列化顺序,属性值越小,顺序越靠前
// serialize 序列化开关
// format 格式
// deserialize 反序列化开关
// defaultValue 默认值
@JSONField (name = "studentName", ordinal = 1)
private String username;
@JSONField (serialize = false, deserialize = false)
private String password;
@JSONField (format = "yyyy-MM-dd")
private Date date;
private String email;
private int age;
}
}