json字符串转Java 泛型对象

依赖包:

<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;

}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值