美文网首页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