美文网首页
【常用】Jackson针对泛型的序列化的工具方法

【常用】Jackson针对泛型的序列化的工具方法

作者: 小胖学编程 | 来源:发表于2022-03-02 16:24 被阅读0次

    如何对带有返回的对象进行输出,可以凝练出下面的工具类。

    import static com.fasterxml.jackson.core.JsonFactory.Feature.INTERN_FIELD_NAMES;
    import static com.fasterxml.jackson.databind.type.TypeFactory.defaultInstance;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Collection;
    import java.util.Map;
    
    import javax.annotation.Nullable;
    
    import org.apache.commons.lang3.StringUtils;
    
    import com.fasterxml.jackson.core.JsonFactory;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.JavaType;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class ObjectMapperUtils {
    
        private static final String EMPTY_JSON = "{}";
        private static final String EMPTY_ARRAY_JSON = "[]";
        //解决jackson2.9.x版本内存泄露的问题,详见[2] Jackson2.x中内存泄露的风险点—封装的intern逻辑
        private static final ObjectMapper MAPPER = new ObjectMapper(new JsonFactory().disable(INTERN_FIELD_NAMES));
    
    
        public static String toJSON(@Nullable Object obj) {
            if (obj == null) {
                return null;
            }
            try {
                return MAPPER.writeValueAsString(obj);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 实现类型的强转。能实现【父类-->子类】的强转。
         * 这一点在{@code (父类)子类}是实现不了的。
         */
        public static <T> T value(Object rawValue, Class<T> type) {
            return MAPPER.convertValue(rawValue, type);
        }
    
        /**
         * 注意,一般情况不推荐使用本方法,因为开销还是略大,可以选择的几个方式是:
         * <p>
         * 1. 直接 {@link #fromJSON} 解析,适用于本身也是要解析JSON并生成DTO,并且是主要分支的场景
         * 2. 自己编写一个方法,只检查第一个字符,适合内部特定数据结构兼容的快速检查,并不需要完整的 JSON 检查
         */
        public static boolean isJSONWithHeavyweight(String jsonStr) {
            if (StringUtils.isBlank(jsonStr)) {
                return false;
            }
            try (JsonParser parser = new ObjectMapper().getFactory().createParser(jsonStr)) {
                while (parser.nextToken() != null) {
                    // do nothing.
                }
                return true;
            } catch (IOException ioe) {
                return false;
            }
        }
    
        /**
         * 轻量级的校验方法
         */
        public static boolean isJSONWithLightweight(String jsonStr) {
            if (StringUtils.isBlank(jsonStr)) {
                return false;
            }
            return jsonStr.startsWith("{") || jsonStr.startsWith("[");
        }
    
    
        /**
         * 带有泛型对象的强转
         */
        public static <T> T value(Object rawValue, TypeReference<T> type) {
            return MAPPER.convertValue(rawValue, type);
        }
    
        public static <T> T value(Object rawValue, JavaType type) {
            return MAPPER.convertValue(rawValue, type);
        }
    
    
        /**
         * 支持带泛型的集合反序列化输出
         */
        public static <E, T extends Collection<E>> T fromJSON(String json,
                Class<? extends Collection> collectionType, Class<E> valueType) {
            if (StringUtils.isEmpty(json)) {
                json = EMPTY_ARRAY_JSON;
            }
            try {
                return MAPPER.readValue(json,
                        defaultInstance().constructCollectionType(collectionType, valueType));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 支持带有泛型的Map的输出
         */
        public static <K, V, T extends Map<K, V>> T fromJSON(String json, Class<? extends Map> mapType,
                Class<K> keyType, Class<V> valueType) {
            if (StringUtils.isEmpty(json)) {
                json = EMPTY_JSON;
            }
            try {
                return MAPPER.readValue(json,
                        defaultInstance().constructMapType(mapType, keyType, valueType));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
    
        public static <T> T fromJSON(InputStream inputStream, Class<T> type) {
            try {
                return MAPPER.readValue(inputStream, type);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
    
        /**
         * 当json中只有bean部分属性时,更新一个存在的bean,只覆盖该部分的属性。
         * 当存在相同的属性时,json中属性的优先级明显会更高。
         */
        public static <T> T update(T rawValue, String jsonString) {
            try {
                return MAPPER.readerForUpdating(rawValue).readValue(jsonString);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static <T> T fromJSON(Object value, Class<T> valueType) {
            if (value == null) {
                return null;
            } else if (value instanceof String) {
                return fromJSON((String) value, valueType);
            } else if (value instanceof byte[]) {
                return fromJSON((byte[]) value, valueType);
            } else {
                return null;
            }
        }
    
        public static <T> T fromJSON(@Nullable byte[] bytes, Class<T> valueType) {
            if (bytes == null) {
                return null;
            }
            try {
                return MAPPER.readValue(bytes, valueType);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static <T> T fromJSON(@Nullable String json, Class<T> valueType) {
            if (json == null) {
                return null;
            }
            try {
                return MAPPER.readValue(json, valueType);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
      
        public static <T> T parseObject(String str, TypeReference<T> type) {
            try {
                return MAPPER.readValue(str, type);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
    

    对二级数组进行反序列化的操作?

        public static void main(String[] args) {
            List<List<Integer>> v1 = Lists.newArrayList(Lists.newArrayList(1, 2, 3), Lists.newArrayList(4, 2, 3));
            //二维数组的反序列化
            List<List<Integer>> lists = parseObject(toJSON(v1), new TypeReference<List<List<Integer>>>() {
            });
            System.out.println(lists);
        }
    

    推荐阅读

    json解析工具类

    [2] Jackson2.x中内存泄露的风险点—封装的intern逻辑

    相关文章

      网友评论

          本文标题:【常用】Jackson针对泛型的序列化的工具方法

          本文链接:https://www.haomeiwen.com/subject/hdhtkrtx.html