1.1.1. 磨刀工具类 —— JsonUtils
1. Maven依赖
Spring Boot
项目
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
非Spring Boot
项目
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
2. 代码
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import df.zhang.util.date.DatePattern;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;
/**
* JSON序列化或反序列化工具,使用{@link ObjectMapper}实现。
*
* @author df.zhang Email: 84154025@qq.com
* @date 2019-04-21
* @since 1.0.0
*/
public final class JsonUtils {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
static {
// 关闭序列化时遭遇空对象(对象中无任何属性)的错误
OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 关闭反序列化时,找不到对应属性或set方法时的错误。
OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 设置值为null的属性不参与序列化
OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 禁用序列化时间对象时,输出为时间戳的特性
OBJECT_MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// 驼峰转蛇形命名法(下划线)
OBJECT_MAPPER.setPropertyNamingStrategy(PropertyNamingStrategy.SnakeCaseStrategy.SNAKE_CASE);
// 自定义java time模块
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DatePattern.DATETIME_YYYY_MM_DD_HH_MM_SS));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DatePattern.DATETIME_YYYY_MM_DD_HH_MM_SS));
javaTimeModule.addSerializer(Date.class, new DateSerializer(false, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));
javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String dateString = jsonParser.getText().trim();
if (StringUtils.isNotBlank(dateString)) {
return Date.from(LocalDateTime.parse(dateString).atZone(ZoneId.systemDefault()).toInstant());
}
return null;
}
});
javaTimeModule.addSerializer(Instant.class, new JsonSerializer<Instant>() {
@Override
public void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (instant == null) {
return;
}
jsonGenerator.writeString(DatePattern.DATETIME_YYYY_MM_DD_HH_MM_SS.format(instant.atZone(ZoneId.systemDefault())));
}
});
javaTimeModule.addDeserializer(Instant.class, new JsonDeserializer<Instant>() {
@Override
public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String dateString = jsonParser.getText().trim();
if (StringUtils.isNotBlank(dateString)) {
return LocalDateTime.parse(dateString).atZone(ZoneId.systemDefault()).toInstant();
}
return null;
}
});
OBJECT_MAPPER.registerModule(new ParameterNamesModule());
// 添加Jdk8模块,支持Optional
OBJECT_MAPPER.registerModule(new Jdk8Module());
// 添加java time模块
OBJECT_MAPPER.registerModule(javaTimeModule);
}
/**
* 获取全局静态资源{@link ObjectMapper}对象。
*
* @return com.fasterxml.jackson.databind.ObjectMapper
* @date 2019-05-04 16:11
* @author df.zhang
* @since 1.0.0
*/
public static ObjectMapper getObjectMapper() {
return OBJECT_MAPPER;
}
/**
* 将任意对象序列化为JSON字符串,具体输出内容由当前类{@link ObjectMapper}的配置决定。详情参考类说明。
*
* @param obj 任意对象。
* @return java.lang.String
* @date 2019-04-21 21:59
* @author df.zhang
* @since 1.0.0
*/
public static String serialize(Object obj) {
if (Objects.isNull(obj)) {
return "{}";
}
try {
return OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
/*
* 如果序列化失败,判断obj的类型。 是数组或集合就输出[],否则输出{}。
*/
Class<?> objClass = obj.getClass();
if (objClass.isArray() || Collection.class.isAssignableFrom(objClass)) {
return "[]";
}
return "{}";
}
}
/**
* 将字符串反序列化为指定类型的对象。要求第一个参数JSON字符串是对象类型字符串,即以{开头,以}结尾;第二个参数的类型不为抽象类、不为接口、有无参构造函数。
* 若需要将[]数组类型json字符串反序列化为集合(含泛型)或更复杂的数组(集合)对象,请使用{@link JsonUtils#deserialize(String, TypeReference)}方法。
*
* @param json JSON字符串
* @param tClass 不为抽象类、不为接口、有无参构造函数的类型
* @return java.util.Optional<T> 返回类型使用{@link Optional}包装,有效避免空指针异常
* @date 2019-04-21 22:35
* @author df.zhang
* @since 1.0.0
*/
public static <T> Optional<T> deserialize(String json, Class<T> tClass) {
if (StringUtils.isBlank(json) || isDeserializeClass(tClass)) {
return Optional.empty();
}
try {
return Optional.ofNullable(OBJECT_MAPPER.readValue(json, tClass));
} catch (IOException e) {
return Optional.empty();
}
}
/**
* 将字符串反序列化为指定类型的对象。允许第一个参数JSON字符串任意对象类型或数组类型字符串,即以“{”开头“}”结尾或“[”开头“]”结尾均可;
* 第二个参数的类型需要为{@link TypeReference}的实现类,该类可以接收复杂的泛型参数,用于在编译时获取到准确的泛型类型。。
*
* @param json JSON字符串
* @param typeReference 任意{@link TypeReference}的实现类,该类可以接收复杂的泛型参数,用于在编译时获取到准确的泛型类型。
* @return java.util.Optional<T> 返回类型使用{@link Optional}包装,有效避免空指针异常
* @date 2019-04-21 22:41
* @author df.zhang
* @since 1.0.0
*/
public static <T> Optional<T> deserialize(String json, TypeReference<T> typeReference) {
if (StringUtils.isBlank(json)) {
return Optional.empty();
}
try {
return Optional.ofNullable(OBJECT_MAPPER.readValue(json, typeReference));
} catch (IOException e) {
return Optional.empty();
}
}
/**
* 检查传入任意类型Class是否满足反序列化要求,即不为抽象类、不为接口、有无参构造函数
*
* @param clazz param1
* @return boolean
* @date 2019-04-21 22:08
* @author df.zhang
* @since 1.0.0
*/
private static boolean isDeserializeClass(Class<?> clazz) {
if (Objects.isNull(clazz)) {
return false;
}
// 判断是否为抽象类或者接口
int mod = clazz.getModifiers();
if (Modifier.isAbstract(mod) || Modifier.isInterface(mod)) {
return false;
}
// 获取无参构造函数
try {
Constructor<?> constructor = clazz.getConstructor();
return constructor != null;
} catch (NoSuchMethodException e) {
return false;
}
}
private JsonUtils() {
throw new UnsupportedOperationException();
}
}
依赖工具类DatePattern.java
import java.time.format.DateTimeFormatter;
/**
* 日期时间格式化常量类,基于Java8的Date&Time API
*
* @author df.zhang Email: 84154025@qq.com
* @date 2019-04-21
* @since 1.0.0
*/
public final class DatePattern {
public static final DateTimeFormatter TIME_HMMSS = DateTimeFormatter.ofPattern("hmmss");
public static final DateTimeFormatter TIME_H_MM_SS = DateTimeFormatter.ofPattern("h:mm:ss");
public static final DateTimeFormatter TIME_AHMMSS = DateTimeFormatter.ofPattern("ahmmss");
public static final DateTimeFormatter TIME_AH_MM_SS = DateTimeFormatter.ofPattern("ah:mm:ss");
public static final DateTimeFormatter TIME_HHMMSS = DateTimeFormatter.ofPattern("HHmmss");
public static final DateTimeFormatter TIME_HH_MM_SS = DateTimeFormatter.ofPattern("HH:mm:ss");
public static final DateTimeFormatter DATE_YYMM = DateTimeFormatter.ofPattern("yyMM");
public static final DateTimeFormatter DATE_YYYYMM = DateTimeFormatter.ofPattern("yyyyMM");
public static final DateTimeFormatter DATE_YYYY_MM = DateTimeFormatter.ofPattern("yyyy-MM");
public static final DateTimeFormatter DATE_YYMMDD = DateTimeFormatter.ofPattern("yyMMdd");
public static final DateTimeFormatter DATE_YYYYMMDD = DateTimeFormatter.ofPattern("yyyyMMdd");
public static final DateTimeFormatter DATE_YY_MM_DD = DateTimeFormatter.ofPattern("yy-MM-dd");
public static final DateTimeFormatter DATE_YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static final DateTimeFormatter DATETIME_YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
public static final DateTimeFormatter DATETIME_YYYYMMDDHHMMSSSSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
public static final DateTimeFormatter DATETIME_YY_MM_DD_H_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd h:mm:ss");
public static final DateTimeFormatter DATETIME_YY_MM_DD_H_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd h:mm:ssZ");
public static final DateTimeFormatter DATETIME_YY_MM_DD_H_MM_SS_UTC = DateTimeFormatter.ofPattern("yyyy-MM-dd h:mm:ss'Z'");
public static final DateTimeFormatter DATETIME_YY_MM_DD_H_MM_SS_SSS = DateTimeFormatter.ofPattern("yyyy-MM-dd h:mm:ss.SSS");
public static final DateTimeFormatter DATETIME_YY_MM_DD_H_MM_SS_SSS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd h:mm:ss.SSSZ");
public static final DateTimeFormatter DATETIME_YY_MM_DD_H_MM_SS_SSS_UTC = DateTimeFormatter.ofPattern("yyyy-MM-dd h:mm:ss.SSS'Z'");
public static final DateTimeFormatter DATETIME_YY_MM_DD_AH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd ah:mm:ss");
public static final DateTimeFormatter DATETIME_YY_MM_DD_AH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd ah:mm:ssZ");
public static final DateTimeFormatter DATETIME_YY_MM_DD_AH_MM_SS_SSS = DateTimeFormatter.ofPattern("yyyy-MM-dd ah:mm:ss.SSS");
public static final DateTimeFormatter DATETIME_YY_MM_DD_AH_MM_SS_SSS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd ah:mm:ss.SSSZ");
public static final DateTimeFormatter DATETIME_YY_MM_DD_AH_MM_SS_SSS_UTC = DateTimeFormatter.ofPattern("yyyy-MM-dd ah:mm:ss.SSS'Z'");
public static final DateTimeFormatter DATETIME_YY_MM_DDTHH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
public static final DateTimeFormatter DATETIME_YY_MM_DDTHH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
public static final DateTimeFormatter DATETIME_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public static final DateTimeFormatter DATETIME_YYYY_MM_DD_HH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ");
public static final DateTimeFormatter DATETIME_YYYY_MM_DDTHH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
public static final DateTimeFormatter DATETIME_YYYY_MM_DDTHH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
public static final DateTimeFormatter DATETIME_YYYY_MM_DDTHH_MM_SS_SSS = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
public static final DateTimeFormatter DATETIME_YYYY_MM_DDTHH_MM_SS_SSS_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
public static final DateTimeFormatter DATETIME_YYYY_MM_DDTHH_MM_SS_SSS_UTC = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
public static final DateTimeFormatter SLASH_DATE_YY_MM_DD = DateTimeFormatter.ofPattern("yy/MM/dd");
public static final DateTimeFormatter SLASH_DATE_YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy/MM/dd");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_H_MM_SS = DateTimeFormatter.ofPattern("yyyy/MM/dd h:mm:ss");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_H_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy/MM/dd h:mm:ssZ");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_AH_MM_SS = DateTimeFormatter.ofPattern("yyyy/MM/dd ah:mm:ss");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_AH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy/MM/dd ah:mm:ssZ");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_AH_MM_SS_UTC = DateTimeFormatter.ofPattern("yyyy/MM/dd ah:mm:ss'Z'");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_HH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ssZ");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DD_HH_MM_SS_UTC = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss'Z'");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DDTHH_MM_SS = DateTimeFormatter.ofPattern("yyyy/MM/dd'T'HH:mm:ss");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DDTHH_MM_SS_SSS = DateTimeFormatter.ofPattern("yyyy/MM/dd'T'HH:mm:ss.SSS");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DDTHH_MM_SS_SSS_Z = DateTimeFormatter.ofPattern("yyyy/MM/dd'T'HH:mm:ss.SSSZ");
public static final DateTimeFormatter SLASH_DATETIME_YYYY_MM_DDTHH_MM_SS_SSS_UTC = DateTimeFormatter.ofPattern("yyyy/MM/dd'T'HH:mm:ss.SSS'Z'");
public static final DateTimeFormatter CHINESE_TIME_H_MM_SS = DateTimeFormatter.ofPattern("h时mm分ss秒");
public static final DateTimeFormatter CHINESE_TIME_AH_MM_SS = DateTimeFormatter.ofPattern("ah时mm分ss秒");
public static final DateTimeFormatter CHINESE_TIME_HH_MM_SS = DateTimeFormatter.ofPattern("HH时mm分ss秒");
public static final DateTimeFormatter CHINESE_DATE_YY_MM_DD = DateTimeFormatter.ofPattern("yy年MM月dd日");
public static final DateTimeFormatter CHINESE_DATE_YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DDH_MM_SS = DateTimeFormatter.ofPattern("yyyy年MM月dd日h时mm分ss秒");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DDH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy年MM月dd日h时mm分ss秒Z");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DDAH_MM_SS = DateTimeFormatter.ofPattern("yyyy年MM月dd日ah时mm分ss秒");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DDAH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy年MM月dd日ah时mm分ss秒Z");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DDHH_MM_SS = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DDHH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒Z");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
public static final DateTimeFormatter CHINESE_DATETIME_YYYY_MM_DD_HH_MM_SS_Z = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
private DatePattern() {
throw new UnsupportedOperationException();
}
}
依赖工具类StringUtils .java
,部分方法参考借鉴Spring
的工具类StringUtils
import java.util.Objects;
/**
* 字符串操作类,一些常用的字符串工具集
*
* @author df.zhang Email: 84154025@qq.com
* @date 2019-04-21
* @since 1.0.0
*/
public final class StringUtils {
/**
* 判断字符串是否非空。
*
* @param str 字符串
* @return boolean 非空返回true,空返回false
* @date 2019-04-21 23:20
* @author df.zhang
* @since 1.0.0
*/
public static boolean isNotEmpty(String str) {
return !Objects.isNull(str) && !str.isEmpty();
}
/**
* 判断字符串是否为空。
*
* @param str 字符串
* @return boolean 空返回true,非空返回false
* @date 2019-04-21 23:21
* @author df.zhang
* @since 1.0.0
*/
public static boolean isEmpty(String str) {
return !isNotEmpty(str);
}
/**
* 判断字符串是否非空且并非只包含空白符。此方法验证该字符串至少有一个非空白符的字符时才为真。
*
* @param str 字符串
* @return boolean 字符串长度大于0且至少包含一个非空白符的字符时返回true,否则返回false
* @date 2019-04-21 23:21
* @author df.zhang
* @since 1.0.0
*/
public static boolean isNotBlank(CharSequence str) {
return (!Objects.isNull(str) && str.length() > 0 && containsText(str));
}
/**
* 判断字符串是否非空且并非只包含空白符。此方法验证该字符串至少有一个非空白符的字符时才为真。
*
* @param str 字符串
* @return boolean 字符串长度大于0且至少包含一个非空白符的字符时返回true,否则返回false
* @date 2019-04-21 23:21
* @author df.zhang
* @since 1.0.0
*/
public static boolean isNotBlank(String str) {
return (str != null && !str.isEmpty() && containsText(str));
}
/**
* 判断字符串是否为空或者只包含空白符,即字符串长度为0或者字符串内只有空白符(一个或多个)时,都验证为真。
*
* @param str param1
* @return boolean 字符串长度为0或者字符串内只有空白符(一个或多个)时,都返回true;否则返回false
* @date 2019-04-21 23:25
* @author df.zhang
* @since 1.0.0
*/
public static boolean isBlank(String str) {
return !isNotBlank(str);
}
/**
* 检查文本是否包含非空白符的字符
*
* @param str 字符串
* @return boolean 包含任意非空白符字符时返回true
* @date 2019-04-21 23:28
* @author df.zhang
* @since 1.0.0
*/
private static boolean containsText(CharSequence str) {
int strLen = str.length();
for (int i = 0; i < strLen; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
return true;
}
}
return false;
}
}