1.配置gson替代默认序列化工具
@Configuration
@EnableWebMvc
public class HttpMessageConverterConfig implements WebMvcConfigurer {
@Autowired
private GsonHttpMessageConverter gsonHttpMessageConverter;
/**
* 注册gson消息转换器
*/
@Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
converters.add(gsonHttpMessageConverter);
}
}
2.配置gson的信息转换处理
@Component
public class GsonHttpMessageConverter extends AbstractJsonHttpMessageConverter {
@Autowired
private GsonExclusionStrategy gsonExclusionStrategy;
@Autowired
private JsonSchemaRepo jsonSchemaRepo;
/**
* 用于读取定义的类型的资源,将其转化为JSONObject对象
*/
@Override
protected Object readInternal(Type resolvedType, Reader reader)
throws Exception {
Optional<JsonSchemaEntity> optional = jsonSchemaRepo
.findById(resolvedType.getTypeName());
if (optional.isPresent()) {
// 将reader转换成字符串
BufferedReader br = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
String json = sb.toString();
// json格式校验
JsonNode schema = new JsonNodeReader().fromReader(
new StringReader(optional.get().getJosnSchema()));
JsonNode data = new JsonNodeReader()
.fromReader(new StringReader(json));
ProcessingReport report = JsonSchemaFactory.byDefault()
.getValidator().validate(schema, data);
if (report.isSuccess()) {
// 校验通过
return gsonDeserialize().fromJson(json, resolvedType);
} else {
// 校验没有通过
Iterator<ProcessingMessage> iterator = report.iterator();
StringBuilder msgsb = new StringBuilder();
while (iterator.hasNext()) {
msgsb.append(iterator.next().getMessage());
}
throw new JsonSchemaException("请求的Json格式不正确:{0}", msgsb);
}
} else {
// 不需要校验
return gsonDeserialize().fromJson(reader, resolvedType);
}
}
/**
* 用于在推送此种类型的资源时,将JSONObject对象转化为自定义的格式返回给调用者
* 这里所有的返回JSONObject对象给前端的请求,都会执行此方法
* 原调用Spring的默认的mappingJackson2HttpMessageConverter来处理
*/
@Override
protected void writeInternal(Object o, Type type, Writer writer)
throws Exception {
if (type instanceof ParameterizedType) {
gsonSerialize().toJson(o, type, writer);
} else {
gsonSerialize().toJson(o, writer);
}
}
/**
* Gson基础配置
*
* @return
*/
private GsonBuilder gsonBuilder() {
GsonBuilder b = new GsonBuilder();
// 注册特殊类型格式数据适配器
b.registerTypeAdapter(LocalDateTime.class,
new CustomLocalDateTypeAdapter());
return b;
}
/**
* 序列化Gson配置
*
* @return
*/
private Gson gsonSerialize() {
return gsonBuilder().setExclusionStrategies(gsonExclusionStrategy)
.create();
}
/**
* 反序列化Gson配置
*
* @return
*/
private Gson gsonDeserialize() {
return gsonBuilder().create();
}
}
3.序列化排除策略
@Component
public class GsonExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
if (f.getAnnotation(Expose.class) != null
&& !f.getAnnotation(Expose.class).serialize()) {
// 如果被Expose注解,且Expose的serialize为false的情况下,不序列化
return true;
} else {
return false;
}
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
4.自定义特殊格式数据适配器
4.1 第一种方式,实现JsonDeserializer和JsonSerializer接口
public class LocalDateTypeAdapter implements JsonDeserializer<LocalDateTime>,
JsonSerializer<LocalDateTime> {
private static final DateTimeFormatter FORMAT = DateTimeFormatter.ISO_DATE_TIME;
@Override
public JsonElement serialize(LocalDateTime src, Type typeOfSrc,
JsonSerializationContext context) {
return new JsonPrimitive(src.format(FORMAT));
}
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
return LocalDateTime.parse(json.getAsString(), FORMAT);
}
}
4.2 第二种方式,继承TypeAdapter类
public class CustomLocalDateTypeAdapter extends TypeAdapter<LocalDateTime> {
private static final DateTimeFormatter FORMAT = DateTimeFormatter.ISO_DATE_TIME;
@Override
public void write(JsonWriter out, LocalDateTime value) throws IOException {
if (value == null) {
out.nullValue();
} else {
out.value(value.format(FORMAT));
}
}
@Override
public LocalDateTime read(JsonReader in) throws IOException {
if (in.peek() == null) {
return null;
}
String str = in.nextString();
LocalDateTime date = LocalDateTime.parse(str, FORMAT);
return date;
}
}