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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM