You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tet/snailmall-api-gateway/src/main/java/com/njupt/swg/utils/JsonUtil.java

161 lines
11 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.njupt.swg.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.text.SimpleDateFormat;
/**
* jackson的序列化和反序列化
* 该类是一个工具类主要基于Jackson库提供了一系列用于对象序列化将对象转换为JSON字符串和反序列化将JSON字符串转换为对象的方法
* 同时在类的初始化阶段对Jackson的ObjectMapper进行了一些配置以满足项目中特定的JSON处理需求例如统一日期格式、忽略某些转换错误等。
*/
@Slf4j
public class JsonUtil {
// 创建一个ObjectMapper对象它是Jackson库中用于进行JSON序列化和反序列化操作的核心类后续的各种序列化和反序列化操作都依赖它来实现。
private static ObjectMapper objectMapper = new ObjectMapper();
static {
//所有字段都列入进行转换
// 设置ObjectMapper在序列化时的包含规则这里设置为JsonSerialize.Inclusion.ALWAYS表示所有的字段都会被包含进序列化的结果中
// 即使字段的值为null也会进行序列化处理确保完整的对象结构能在JSON字符串中体现出来。
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
//取消默认转换timestamp形式
// 配置ObjectMapper在序列化日期类型字段时取消将日期转换为时间戳的默认行为这样在序列化后的JSON字符串中日期会以指定的格式呈现而不是时间戳形式。
objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
//忽略空bean转json的错误
// 配置ObjectMapper在尝试将一个空的Java对象没有任何属性值的对象转换为JSON字符串时忽略可能出现的错误
// 使得即使对象为空也能正常进行序列化操作,避免抛出异常导致程序中断。
objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
//统一时间的格式
// 设置ObjectMapper在处理日期类型数据时使用的统一日期格式通过传入一个SimpleDateFormat对象指定了格式为DateTimeUtil.STANDARD_FORMAT在其他地方定义的标准格式
// 保证序列化和反序列化过程中日期格式的一致性和规范性。
objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtil.STANDARD_FORMAT));
//忽略json存在属性但是java对象不存在属性的错误
// 配置ObjectMapper在进行反序列化时忽略JSON字符串中存在但对应的Java对象中不存在的属性所引发的错误
// 这样在JSON数据结构可能发生变化或者不完全匹配Java对象结构时依然能够正常进行反序列化操作提高了程序的兼容性和容错性。
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
/**
* 序列化方法,将对象转为字符串
* 该方法用于将一个Java对象转换为JSON字符串表示形式如果对象为null则直接返回null
* 在转换过程中若出现IO异常例如对象的某些属性无法正常序列化等情况会记录警告日志并返回null。
*
* @param obj 要进行序列化的Java对象可以是任意类型的对象由泛型参数<T>表示其通用性。
* @param <T> 泛型参数用于表示传入对象的类型确保返回的JSON字符串能正确对应相应类型的对象序列化结果。
* @return 返回转换后的JSON字符串如果对象为null或者序列化过程出现异常则返回null。
*/
public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
// 判断传入的对象是否本身就是字符串类型如果是则直接返回该字符串否则使用ObjectMapper将对象转换为JSON字符串并返回。
return obj instanceof String? (String) obj : objectMapper.writeValueAsString(obj);
} catch (IOException e) {
log.warn("parse object to string error", e);
return null;
}
}
/**
* 序列化方法,同上,只是输出的格式是美化的,便于测试
* 该方法与obj2String方法功能类似也是将Java对象转换为JSON字符串不同之处在于它会使用美化的格式输出JSON字符串
* 使得生成的JSON字符串更易于阅读和查看方便在测试等场景下查看对象序列化后的具体结构同样在出现异常时会记录警告日志并返回null。
*
* @param obj 要进行序列化的Java对象可以是任意类型的对象由泛型参数<T>表示其通用性。
* @param <T> 泛型参数用于表示传入对象的类型确保返回的JSON字符串能正确对应相应类型的对象序列化结果。
* @return 返回转换后的JSON字符串如果对象为null或者序列化过程出现异常则返回null正常情况下返回美化格式的JSON字符串。
*/
public static <T> String obj2StringPretty(T obj) {
if (obj == null) {
return null;
}
try {
// 使用ObjectMapper的writerWithDefaultPrettyPrinter方法获取一个能够生成美化格式JSON字符串的写入器
// 然后通过该写入器将对象转换为美化后的JSON字符串并返回。
return obj instanceof String? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (IOException e) {
log.warn("parse object to string error", e);
return null;
}
}
/**
* 比较简单的反序列化的方法,将字符串转为单个对象
* 该方法用于将一个JSON字符串反序列化为指定类型的Java对象在进行反序列化前会先判断字符串是否为空以及指定的目标类是否为null
* 如果有任意一个为空则直接返回null若反序列化过程中出现IO异常例如JSON格式不匹配目标对象结构等情况会记录警告日志并返回null。
*
* @param str 要进行反序列化的JSON字符串包含了要转换为Java对象的数据内容。
* @param clazz 目标Java对象的类型通过传入的Class<T>参数明确指定要将JSON字符串反序列化为哪种类型的对象确保类型的准确性。
* @param <T> 泛型参数用于表示要反序列化得到的对象类型与传入的clazz参数类型相对应。
* @return 返回反序列化后的Java对象如果字符串为空、目标类为null或者反序列化过程出现异常则返回null。
*/
public static <T> T String2Obj(String str, Class<T> clazz) {
if (StringUtils.isEmpty(str) || clazz == null) {
return null;
}
try {
// 判断传入的目标类是否就是字符串类型的Class对象如果是则直接将传入的字符串强制转换并返回因为本身就是字符串无需真正的反序列化操作
// 否则使用ObjectMapper将JSON字符串按照指定的目标类进行反序列化并返回对应的对象。
return clazz.equals(String.class)? (T) str : objectMapper.readValue(str, clazz);
} catch (IOException e) {
log.warn("parse string to obj error", e);
return null;
}
}
/**
* 复杂对象的反序列化(通用)
* 该方法用于处理更复杂的反序列化场景能够将JSON字符串反序列化为复杂类型的对象例如包含泛型的集合类型等
* 通过传入TypeReference类型的参数来指定复杂对象的具体类型信息同样在字符串为空或者TypeReference为null时会直接返回null
* 若反序列化出现异常会记录警告日志并返回null。
*
* @param str 要进行反序列化的JSON字符串包含了要转换为复杂Java对象的数据内容。
* @param typeReference 用于指定复杂对象类型的TypeReference对象通过它可以准确描述包含泛型等复杂结构的对象类型信息确保反序列化的准确性。
* @param <T> 泛型参数用于表示要反序列化得到的复杂对象类型与传入的typeReference所描述的类型相对应。
* @return 返回反序列化后的复杂Java对象如果字符串为空、typeReference为null或者反序列化过程出现异常则返回null。
*/
public static <T> T Str2Obj(String str, TypeReference typeReference) {
if (StringUtils.isEmpty(str) || typeReference == null) {
return null;
}
try {
// 判断传入的TypeReference所表示的类型是否就是字符串类型如果是则直接返回传入的字符串无需反序列化操作
// 否则使用ObjectMapper按照TypeReference指定的复杂类型信息将JSON字符串进行反序列化并返回对应的对象。
return (T) (typeReference.getType().equals(String.class)? str : objectMapper.readValue(str, typeReference));
} catch (IOException e) {
log.warn("parse string to obj error", e);
return null;
}
}
/**
* 第二种方式实现复杂对象的反序列化
* 该方法是另一种实现复杂对象反序列化的方式通过传入集合类型的Class对象以及元素类型的Class对象可以多个用于表示集合中元素的类型信息
* 利用ObjectMapper的类型工厂构建出JavaType对象来准确描述复杂对象的类型结构然后进行反序列化操作
* 在出现异常时同样会记录警告日志并返回null。
*
* @param str 要进行反序列化的JSON字符串包含了要转换为复杂Java对象的数据内容。
* @param collectionClass 表示集合类型的Class对象用于指定要反序列化得到的对象是哪种集合类型如List、Set等
* @param elementClasses 可变参数用于指定集合中元素的类型Class对象可以传入多个按照顺序依次表示集合中各元素的类型信息。
* @param <T> 泛型参数用于表示要反序列化得到的复杂对象类型与传入的collectionClass和elementClasses所构建的类型结构相对应。
* @return 返回反序列化后的复杂Java对象如果反序列化过程出现异常则返回null。
*/
public static <T> T Str2Obj(String str, Class<?> collectionClass, Class<?>... elementClasses) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
try {
return objectMapper.readValue(str, javaType);
} catch (IOException e) {
log.warn("parse string to obj error", e);
return null;
}
}
}