zoukankan      html  css  js  c++  java
  • SpringBoot jackson传入List引起的坑

    一、jackson无法解析value为[]的json

        当入参为{xxxx1:[1,2,3],xxxx2:[obj1,obj2,obj3]}时,springmvn controller接收入参写为Long[] xxxx1,无法解析,报错

        解决方案:

    1.@RequestBody只能使用一次

    2.使用map接收,再用get获取

    二、如上,当数组为POJO时,通过直接map.get然后强制转换,不能成功,使用的时候还是LinkedHashMap

    解决方案:

    1.先将LinkedHashMap转为json,再讲json转为对象,如下JsonUtils的convertObject方法,转换List使用convertObjectList方法

    package com.performancetest.common.utils;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    public class JsonUtils {
    
        /**
         * <p>
         * 对象转JSON字符串
         * </p>
         */
        public static String object2Json(Object obj) {
            String result = null;
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                result = objectMapper.writeValueAsString(obj);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }
    
        public static Map object2Map(Object obj) {
            String object2Json = object2Json(obj);
            Map<?, ?> result = jsonToMap(object2Json);
            return result;
        }
    
        /**
         * <p>
         * JSON字符串转Map对象
         * </p>
         */
        public static Map<?, ?> jsonToMap(String json) {
            return json2Object(json, Map.class);
        }
    
        /**
         * <p>
         * JSON转Object对象
         * </p>
         *
         */
        public static <T> T json2Object(String json, Class<T> cls) {
            T result = null;
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                result = objectMapper.readValue(json, cls);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return result;
        }
    
    
        public static <T> T convertObject(Object srcObject, Class<T> destObjectType) {
            String jsonContent = object2Json(srcObject);
            return json2Object(jsonContent, destObjectType);
        }
    
        public static <T> List  convertObjectList(List<LinkedHashMap> list, Class<T> destObjectType){
            List result =new ArrayList<>();
            list.stream().forEach(x->{
                result.add(convertObject(x,destObjectType));
            });
            return result;
        }
    
    }

    三、如上转换时,报出错,jackson转换DateFormat类型时,不支持yyyy-MM-DD HH-mm-ss格式的日期,报错

    解决方案:

    方案1.在Date类型上加@JsonFormat( pattern="yyyy-MM-dd HH:mm:ss"),如下

    (弊端:每个字段都得加,麻烦,没从根本上解决问题,不推荐,推荐方案2)

    @JsonFormat( pattern="yyyy-MM-dd HH:mm:ss")
        private Date updateTime;

    方案2.

    1.重写DateFormat子类,解析的实收优先用yyyy-MM-dd HH:mm:ss类型解析,不行再用父类

    (这里遇到一个坑,启动时报calendar空指针异常,所以在构造函数里加了

    this.calendar = dateFormat.getCalendar(); )
    package com.performancetest.config;
    
    
    import java.text.DateFormat;
    import java.text.FieldPosition;
    import java.text.ParseException;
    import java.text.ParsePosition;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class MyDateFormat extends DateFormat {
    
        private DateFormat dateFormat;
    
        private SimpleDateFormat format1 = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
    
        public MyDateFormat(DateFormat dateFormat) {
            this.dateFormat = dateFormat;
            //要添加父类的calendar属性,否则会报空指针异常
            this.calendar = dateFormat.getCalendar();
        }
    
        @Override
        public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
            return dateFormat.format(date, toAppendTo, fieldPosition);
        }
    
        @Override
        public Date parse(String source, ParsePosition pos) {
    
            Date date = null;
    
            try {
    
                date = format1.parse(source, pos);
            } catch (Exception e) {
    
                date = dateFormat.parse(source, pos);
            }
    
            return date;
        }
    
        // 主要还是装饰这个方法
        @Override
        public Date parse(String source) throws ParseException {
    
            Date date = null;
    
            try {
    
                // 先按我的规则来
                date = format1.parse(source);
            } catch (Exception e) {
    
                // 不行,那就按原先的规则吧
                date = dateFormat.parse(source);
            }
    
            return date;
        }
    
        // 这里装饰clone方法的原因是因为clone方法在jackson中也有用到
        @Override
        public Object clone() {
            Object format = dateFormat.clone();
            return new MyDateFormat((DateFormat) format);
        }
    }
    View Code

    2.将新写的子类关联到WebConfig中的MappingJackson2HttpMessageConverter Bean,如下代码

    package com.performancetest.config;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
    
    import java.text.DateFormat;
    
    @Configuration
    public class WebConfig {
    
        @Autowired
        private Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder;
    
        @Bean
        public MappingJackson2HttpMessageConverter MappingJsonpHttpMessageConverter() {
    
            ObjectMapper mapper = jackson2ObjectMapperBuilder.build();
    
            //MyDateFormate解决jackson反序列formdate不支持YYYY-MM-DD HH-mm-ss的格式
            // ObjectMapper为了保障线程安全性,里面的配置类都是一个不可变的对象
            // 所以这里的setDateFormat的内部原理其实是创建了一个新的配置类
            DateFormat dateFormat = mapper.getDateFormat();
            MyDateFormat myDateFormat = new MyDateFormat(dateFormat);
            mapper.setDateFormat(myDateFormat);
    
            MappingJackson2HttpMessageConverter mappingJsonpHttpMessageConverter = new MappingJackson2HttpMessageConverter(
                    mapper);
            return mappingJsonpHttpMessageConverter;
        }
    }
    View Code
  • 相关阅读:
    ThinkPHP运算符 与 SQL运算符 对比表
    [Java 8] (6) Lambda与资源管理
    Codeforces Round #275 (Div. 2) C
    HOJ 2245 浮游三角胞(数学啊 )
    [UVALive 6663 Count the Regions] (dfs + 离散化)
    浅解ARC中的 __bridge、__bridge_retained和__bridge_transfer
    SpringMVC: web.xml中声明DispatcherServlet时一定要加入load-on-startup标签
    Unity3d 4.3.4f1执行项目
    更新Windows ActiveX,Ios
    C++11: final与override
  • 原文地址:https://www.cnblogs.com/zipon/p/9915412.html
Copyright © 2011-2022 走看看