美文网首页Java web
Json工具类的封装

Json工具类的封装

作者: 梦想实现家_Z | 来源:发表于2019-03-23 16:23 被阅读0次

从学习java开始,必然是要接触到序列化的,json序列化就是其中之一,而且是使用的比较频繁的一种序列化方式。自从某网站学习了Geely老师的课程后,决定把json序列化相关的知识做一次小的总结,并最终总结出JsonUtil工具类。
1.相关的jar依赖

       <!--json序列化包-->
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>
        <!--日志包-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>
        <!--lombok工具包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>
        <!--工具包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.8.1</version>
        </dependency>

2.对象序列化成json字符串

   /**
     * json工具类
     * final修饰符是为了避免创建JsonUtil的子类
     */
    @Slf4j
    public final class JsonUtil {

        /**
         * 防止使用者直接new JsonUtil()
         */
        private JsonUtil() {
        }


        private static ObjectMapper objectMapper = new ObjectMapper();
        /**
          *  注意以下配置,特别重要
          */
        static {
            //对象所有字段全部列入序列化
            objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
            /**
             * 所有日期全部格式化成时间戳
             * 因为即使指定了DateFormat,也不一定能满足所有的格式化情况,所以统一为时间戳,让使用者按需转换
             */
            objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, true);
            /**
             * 忽略空Bean转json的错误
             * 假设只是new方式创建对象,并且没有对里面的属性赋值,也要保证序列化的时候不报错
             */
            objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
            /**
             * 忽略反序列化中json字符串中存在,但java对象中不存在的字段
             */
            objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }

        /**
         * 对象转换成json字符串
         *
         * @param obj
         * @param <T>
         * @return
         */
        public static <T> String obj2String(T obj) {
            if (Objects.isNull(obj)) {
                return null;
            }
            try {
                return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
            } catch (Exception e) {
                log.warn("Parse object to String error", e);
                //即使序列化出错,也要保证程序走下去
                return null;
            }
        }

        /**
         * 对象转json字符串(带美化效果)
         *
         * @param obj
         * @param <T>
         * @return
         */
        public static <T> String obj2StringPretty(T obj) {
            if (Objects.isNull(obj)) {
                return null;
            }
            try {
                return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
            } catch (Exception e) {
                log.warn("Parse object to String error", e);
                //即使序列化出错,也要保证程序走下去
                return null;
            }
        }

/**
     * 主函数,用于测试
     *
     * @param args
     */
    public static void main(String[] args) {
        User user = new User("Zz", 26);
       /**
         * 普通序列化
         */
        System.out.println(JsonUtil.obj2String(user));
        /**
         * 美化序列化
         */
        System.out.println(JsonUtil.obj2StringPretty(user));
    }

    /**
     * 实体类User
     */
    @Data
    @ToString
    @AllArgsConstructor
    public static class User {
        public User() {
        }
        /**
         * 名字
         */
        private String name;
        /**
         * 年龄
         */
        private int age;
    }
}

上面主函数的测试结果:

{"name":"Zz","age":26}

//美化后的结果
{
  "name" : "Zz",
  "age" : 26
}

3.反序列化(json字符串转对象)

/**
         * json字符串转简单对象
         *
         * @param json
         * @param clazz
         * @param <T>
         * @return
         */
        public static <T> T string2Obj(String json, Class<T> clazz) {
            if (StringUtils.isEmpty(json) || Objects.isNull(clazz)) {
                return null;
            }
            try {
                return clazz.equals(String.class) ? (T) json : objectMapper.readValue(json, clazz);
            } catch (Exception e) {
                log.warn("Parse String to Object error", e);
                //即使序列化出错,也要保证程序走下去
                return null;
            }
        }

主函数测试:

/**
     * 主函数,用于测试
     *
     * @param args
     */
    public static void main(String[] args) {
        /**
          * 特意多加一个额外的字段:sex,
          * 之所以还能正确序列化成功,
          *是因为设置DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES=false
         */
        String json = "{\"name\":\"Zz\",\"age\":26,\"sex\":\"男\"}";
        User user = JsonUtil.string2Obj(json, User.class);
        // User对象要重写toString()方法
        System.out.println(user);
    }

测试结果:

User(name=Zz, age=26)

4.复杂对象的反序列化
在平时开发中也是会遇到需要将字符串反序列化成类似List<User>的情况,如果使用上面的string2Obj()方法,Class参数是给List.class还是User.class,貌似只能给List.class才能让程序正确运行,但是得到的结果却不是我们预期的List<User>;所以,我们需要对string2Obj()方法做一次增强:

/**
         * json字符串转复杂对象
         *
         * @param json
         * @param typeReference 例如:new TypeReference<List<User>>(){}
         * @param <T>           例如:List<User>
         * @return
         */
        public static <T> T string2Obj(String json, TypeReference<T> typeReference) {
            if (StringUtils.isEmpty(json) || Objects.isNull(typeReference)) {
                return null;
            }
            try {
                return (T)(typeReference.getType().equals(String.class) ? (T) json : objectMapper.readValue(json, typeReference));
            } catch (IOException e) {
                log.warn("Parse String to Object error", e);
                //即使序列化出错,也要保证程序走下去
                return null;
            }
        }


        /**
         * json字符串转复杂对象
         *
         * @param json
         * @param collectionClass 例如:List.class
         * @param elementClasses  例如:User.class
         * @param <T>             例如:List<User>
         * @return
         */
        public static <T> T string2Obj(String json, Class<?> collectionClass, Class<?>... elementClasses) {
            if (StringUtils.isEmpty(json) || Objects.isNull(collectionClass) || Objects.isNull(elementClasses)) {
                return null;
            }
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
            try {
                return objectMapper.readValue(json, javaType);
            } catch (IOException e) {
                log.warn("Parse String to Object error", e);
                //即使序列化出错,也要保证程序走下去
                return null;
            }
        }

测试:

/**
     * 主函数,用于测试
     *
     * @param args
     */
    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        list.add(new User("Zz", 26));
        list.add(new User("james", 30));
        list.add(new User("kelly", 22));
        list.add(new User("itachi", 20));
        list.add(new User("naruto", 16));

        //先做序列化
        String json = JsonUtil.obj2String(list);
        System.out.println("序列化结果:");
        System.out.println(json);

        //拿到序列化后的字符串再做反序列化
        List<User> result1 = JsonUtil.string2Obj(json, new TypeReference<List<User>>(){});
        System.out.println("反序列化结果1:");
        System.out.println(result1);

        //拿到序列化后的字符串再做反序列化
        List<User> result2 = JsonUtil.string2Obj(json, List.class, User.class);
        System.out.println("反序列化结果2:");
        System.out.println(result2);
    }

测试结果:

//序列化结果:
[{"name":"Zz","age":26},{"name":"james","age":30},{"name":"kelly","age":22},{"name":"itachi","age":20},{"name":"naruto","age":16}]
//反序列化结果:
[JsonMain.User(name=Zz, age=26), JsonMain.User(name=james, age=30), JsonMain.User(name=kelly, age=22), JsonMain.User(name=itachi, age=20), JsonMain.User(name=naruto, age=16)]
//反序列化结果:
[JsonMain.User(name=Zz, age=26), JsonMain.User(name=james, age=30), JsonMain.User(name=kelly, age=22), JsonMain.User(name=itachi, age=20), JsonMain.User(name=naruto, age=16)]

5.最终得到的产物JsonUtil

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.util.Objects;

@Slf4j
public final class JsonUtil {

    /**
     * 防止使用者直接new JsonUtil()
     */
    private JsonUtil() {
    }


    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        //对象所有字段全部列入序列化
        objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS);
        /**
         * 所有日期全部格式化成时间戳
         * 因为即使指定了DateFormat,也不一定能满足所有的格式化情况,所以统一为时间戳,让使用者按需转换
         */
        objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, true);
        /**
         * 忽略空Bean转json的错误
         * 假设只是new方式创建对象,并且没有对里面的属性赋值,也要保证序列化的时候不报错
         */
        objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
        /**
         * 忽略反序列化中json字符串中存在,但java对象中不存在的字段
         */
        objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 对象转换成json字符串
     *
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String obj2String(T obj) {
        if (Objects.isNull(obj)) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.warn("Parse object to String error", e);
            //即使序列化出错,也要保证程序走下去
            return null;
        }
    }

    /**
     * 对象转json字符串(带美化效果)
     *
     * @param obj
     * @param <T>
     * @return
     */
    public static <T> String obj2StringPretty(T obj) {
        if (Objects.isNull(obj)) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (Exception e) {
            log.warn("Parse object to String error", e);
            //即使序列化出错,也要保证程序走下去
            return null;
        }
    }

    /**
     * json字符串转简单对象
     *
     * @param <T>
     * @param json
     * @param clazz
     * @return
     */
    public static <T> T string2Obj(String json, Class<T> clazz) {
        if (StringUtils.isEmpty(json) || Objects.isNull(clazz)) {
            return null;
        }
        try {
            return clazz.equals(String.class) ? (T) json : objectMapper.readValue(json, clazz);
        } catch (Exception e) {
            log.warn("Parse String to Object error", e);
            //即使序列化出错,也要保证程序走下去
            return null;
        }
    }

    /**
     * json字符串转复杂对象
     *
     * @param json
     * @param typeReference 例如:new TypeReference<List<User>>(){}
     * @param <T>           例如:List<User>
     * @return
     */
    public static <T> T string2Obj(String json, TypeReference<T> typeReference) {
        if (StringUtils.isEmpty(json) || Objects.isNull(typeReference)) {
            return null;
        }
        try {
            return (T)(typeReference.getType().equals(String.class) ? (T) json : objectMapper.readValue(json, typeReference));
        } catch (Exception e) {
            log.warn("Parse String to Object error", e);
            //即使序列化出错,也要保证程序走下去
            return null;
        }
    }


    /**
     * json字符串转复杂对象
     *
     * @param json
     * @param collectionClass 例如:List.class
     * @param elementClasses  例如:User.class
     * @param <T>             例如:List<User>
     * @return
     */
    public static <T> T string2Obj(String json, Class<?> collectionClass, Class<?>... elementClasses) {
        if (StringUtils.isEmpty(json) || Objects.isNull(collectionClass) || Objects.isNull(elementClasses)) {
            return null;
        }
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
        try {
            return objectMapper.readValue(json, javaType);
        } catch (Exception e) {
            log.warn("Parse String to Object error", e);
            //即使序列化出错,也要保证程序走下去
            return null;
        }
    }
}

总结:这个JsonUtil在实际开发环境中经常会使用,小伙伴们可以直接将这个类使用的平时的开发当中。也特别感谢Geely老师,让我对json序列化操作有了更深的理解。

相关文章

网友评论

    本文标题:Json工具类的封装

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