依赖包:
<dependencies>
<!-- Jackson core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
<!-- Jackson Guava module -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
<version>2.13.0</version>
</dependency>
<!-- Guava library -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
</dependencies>
工具类:
import cn.enums.DateTimeEnum;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.*;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
/**
* 简单封装Jackson,实现 JSON 字符串与 Java 对象的互转
*/
public class JsonUtils {
private static final ObjectMapper NON_EMPTY = newObjectMapper(Include.NON_EMPTY);
private static final ObjectMapper NON_DEFAULT = newObjectMapper(Include.NON_DEFAULT);
private static final ObjectMapper ALWAYS = newObjectMapper(Include.ALWAYS);
private static final ObjectMapper NON_NULL = newObjectMapper(Include.NON_NULL);
/**
* 只输出非Null且非Empty(如List.isEmpty)的属性到 Json
*/
public static String toNonEmptyJson(Object object) {
try {
return NON_EMPTY.writeValueAsString(object);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 只输出初始值被改变的属性到 Json
*/
public static String toNonDefaultJson(Object object) {
try {
return NON_DEFAULT.writeValueAsString(object);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 可输出全部字段到 json
*/
public static String toAlwaysJson(Object object) {
try {
return ALWAYS.writeValueAsString(object);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 仅输出非 null 字段到 json
*/
public static String toNonNullJson(Object object) {
try {
return NON_NULL.writeValueAsString(object);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 反序列化无泛型的简单 bean
*/
public static <T> T fromJson(String jsonString, Class<T> clazz) {
try {
return ALWAYS.readValue(jsonString, clazz);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 反序列化带有泛型的复杂对象,如List<Bean>,可以先使用方法 constructParametricType 构造类型,然后调用本方法
*
* @see #constructParametricType(Class, Class...)
*/
public static <T> T fromJson(String jsonString, JavaType javaType) {
try {
return ALWAYS.readValue(jsonString, javaType);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> T fromJson(String jsonString, TypeReference<T> typeReference) {
try {
return ALWAYS.readValue(jsonString, typeReference);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> List<T> fromJsonToList(String json, Class<T> elementClass) {
return fromJson(json, constructParametricType(List.class, elementClass));
}
public static <K, V> Map<K, V> fromJsonToMap(String json, Class<K> keyClass, Class<V> valueClass) {
return fromJson(json, constructParametricType(Map.class, keyClass, valueClass));
}
public static Map<String, Object> fromJsonToMap(String json) {
return fromJson(json, constructParametricType(Map.class, String.class, Object.class));
}
public static <K, V> List<Map<K, V>> fromJsonToMapList(String json, Class<K> keyClass, Class<V> valueClass) {
return fromJson(json, constructParametricType(List.class, constructParametricType(Map.class, keyClass, valueClass)));
}
/**
* 构造泛型的 JavaType,如:<br>
* {@code ArrayList<MyBean>}, 则调用 constructParametricType(ArrayList.class,MyBean.class)<br>
* {@code HashMap<String, MyBean>}, 则调用 constructParametricType(HashMap.class,String.class, MyBean.class)
* {@code MyBean3<MyBean2<MyBean1>>}, 则调用 javaType = constructParametricType(MyBean2.class,MyBean1.class);
* constructParametricType(MyBean3.class, javaType);
*/
public static JavaType constructParametricType(Class<?> parametrized, Class<?>... elementClasses) {
return ALWAYS.getTypeFactory().constructParametricType(parametrized, elementClasses);
}
/**
* 参考 {@link JsonUtils#constructParametricType(Class, Class[])}
*/
public static JavaType constructParametricType(Class<?> parametrized, JavaType... parameterTypes) {
return ALWAYS.getTypeFactory().constructParametricType(parametrized, parameterTypes);
}
/**
* 创建一个新的 {@link ObjectMapper},并进行一些关键设置,
* 并注册这些扩展Module:{@link GuavaModule}、{@link JavaTimeModule}、{@link Jdk8Module}。
*
* @param include 设置输出时包含属性的风格,此设置仅对序列化有效,反序列化时不同的 Include 并没有区别
* @return {@link ObjectMapper}
*/
public static ObjectMapper newObjectMapper(Include include) {
final ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(include);
//设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//禁止使用int代表Enum的order()来反序列化Enum,非常危险
mapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
// 禁用时间戳风格的日期时间序列化,该设置对 java.util.Date(及其他旧的日期时间类)和 Java8time 都有影响
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// 设置时区(使用操作系统的设置),该设置仅对 java.util.Date(及其他旧的日期时间类)有影响
mapper.setTimeZone(TimeZone.getDefault());
// 设置格式化风格,该方法内部会禁用 WRITE_DATES_AS_TIMESTAMPS,从而使此“格式”仅对 java.util.Date(及其他旧的日期时间类)有影响
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 注册要支持的第三方类库
mapper.registerModule(new GuavaModule());
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new Jdk8Module());
registerCustomModule(mapper);
return mapper;
}
public static void registerCustomModule(ObjectMapper mapper) {
SimpleModule module = new SimpleModule();
module.addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer(DateTimeEnum.COMMON_DATE_TIME.getFormatter()));
module.addDeserializer(LocalDate.class, new CustomLocalDateDeserializer(DateTimeEnum.COMMON_DATE.getFormatter()));
module.addDeserializer(LocalTime.class, new CustomLocalTimeDeserializer(DateTimeEnum.COMMON_TIME.getFormatter()));
module.addDeserializer(YearMonth.class, new CustomYearMonthDeserializer(DateTimeEnum.CHN_MONTH.getFormatter()));
module.addDeserializer(MonthDay.class, new CustomMonthDayDeserializer(DateTimeEnum.CHN_MONTH_DATE.getFormatter()));
mapper.registerModule(module);
}
private static class CustomLocalDateTimeDeserializer extends LocalDateTimeDeserializer {
private static final long serialVersionUID = -2007179451387522834L;
private final DateTimeFormatter formatterOnFailure;
private CustomLocalDateTimeDeserializer(DateTimeFormatter formatterOnFailure) {
super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
this.formatterOnFailure = formatterOnFailure;
}
@Override
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
try {
return super.deserialize(parser, context);
} catch (IOException e) {
String string = parser.getText().trim();
return LocalDateTime.parse(string, formatterOnFailure);
}
}
}
private static class CustomLocalDateDeserializer extends LocalDateDeserializer {
private static final long serialVersionUID = 3218254419776254843L;
private final DateTimeFormatter formatterOnFailure;
private CustomLocalDateDeserializer(DateTimeFormatter formatterOnFailure) {
super(DateTimeFormatter.ISO_LOCAL_DATE);
this.formatterOnFailure = formatterOnFailure;
}
@Override
public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
try {
return super.deserialize(parser, context);
} catch (IOException e) {
String string = parser.getText().trim();
return LocalDate.parse(string, formatterOnFailure);
}
}
}
private static class CustomLocalTimeDeserializer extends LocalTimeDeserializer {
private static final long serialVersionUID = 7818627100921395338L;
private final DateTimeFormatter formatterOnFailure;
private CustomLocalTimeDeserializer(DateTimeFormatter formatterOnFailure) {
super(DateTimeFormatter.ISO_LOCAL_TIME);
this.formatterOnFailure = formatterOnFailure;
}
@Override
public LocalTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
try {
return super.deserialize(parser, context);
} catch (IOException e) {
String string = parser.getText().trim();
return LocalTime.parse(string, formatterOnFailure);
}
}
}
private static class CustomYearMonthDeserializer extends YearMonthDeserializer {
private static final long serialVersionUID = 707238372357810030L;
private final DateTimeFormatter formatterOnFailure;
private CustomYearMonthDeserializer(DateTimeFormatter formatterOnFailure) {
super(DateTimeFormatter.ofPattern("uuuu-MM"));
this.formatterOnFailure = formatterOnFailure;
}
@Override
public YearMonth deserialize(JsonParser parser, DeserializationContext context) throws IOException {
try {
return super.deserialize(parser, context);
} catch (IOException e) {
return YearMonth.parse(parser.getText().trim(), formatterOnFailure);
}
}
}
private static class CustomMonthDayDeserializer extends MonthDayDeserializer {
private static final long serialVersionUID = 6988597109082367232L;
private final DateTimeFormatter formatterOnFailure;
private CustomMonthDayDeserializer(DateTimeFormatter formatterOnFailure) {
super(null);
this.formatterOnFailure = formatterOnFailure;
}
@Override
public MonthDay deserialize(JsonParser parser, DeserializationContext context) throws IOException {
try {
return super.deserialize(parser, context);
} catch (IOException e) {
return MonthDay.parse(parser.getText().trim(), formatterOnFailure);
}
}
}
}
import lombok.Getter;
import java.time.format.DateTimeFormatter;
public enum DateTimeEnum {
COMMON_DATE_TIME("yyyy-MM-dd HH:mm:ss"),
COMMON_DATE_MINUTE("yyyy-MM-dd HH:mm"),
COMMON_DATE("yyyy-MM-dd"),
COMMON_MONTH("yyyy-MM"),
COMMON_TIME("HH:mm:ss"),
COMMON_MINUTE("HH:mm"),
NUMERIC_DATE_TIME("yyyyMMddHHmmss"),
NUMERIC_DATE_MINUTE("yyyyMMddHHmm"),
NUMERIC_DATE("yyyyMMdd"),
NUMERIC_MONTH("yyyyMM"),
NUMERIC_TIME("HHmmss"),
NUMERIC_MINUTE("HHmm"),
CHN_DATE_TIME("yyyy年MM月dd日 HH时mm分ss秒"),
CHN_DATE_MINUTE("yyyy年MM月dd日 HH时mm分"),
CHN_DATE("yyyy年MM月dd日"),
CHN_MONTH_DATE("MM月dd日"),
CHN_MONTH("yyyy年MM月"),
CHN_TIME("HH时mm分ss秒"),
CHN_MINUTE("HH时mm分");
@Getter
private final String pattern;
@Getter
public final DateTimeFormatter formatter;
DateTimeEnum(String pattern) {
this.pattern = pattern;
this.formatter = DateTimeFormatter.ofPattern(pattern);
}
}
使用:
public static ResponseDTO<List<HealthData>> realtime(List<String> snList) {
JSONObject params = new JSONObject();
params.put("sns", snList);
String uri = "/xxx";
HttpRequest request = HttpUtil.createPost(urlRoot + uri);
request.header("Content-Type", "application/json");
request.header("accessToken", accessToken);
request.body(params.toJSONString());
HttpResponse response = request.execute();
TypeReference<ResponseDTO<List<HealthData>>> typeReference = new TypeReference<ResponseDTO<List<HealthData>>>() {
};
return JsonUtils.fromJson(response.body(), typeReference);
}
import lombok.Data;
@Data
public class ResponseDTO<T> {
/**
* 返回的 code 码
*/
private int code;
/**
* 返回值信息
*/
private String message;
/**
* 返回值内容
*/
private T data;
}
import lombok.Data;
@Data
public class HealthData {
private String sn;
private RealData realData;
}
import lombok.Data;
@Data
public class RealData {
private String heart;
private String breathe;
private Integer heartStatus;
private Integer breatheStatus;
private Integer status;
private Long timestamp;
private Boolean goodData;
}