Fegin が呼び出すと、ジャクソン時間変換例外の問題が解決されました

最近、fegin を使用して呼び出しを行うときに、文字列を日付に変換するときに jackson がサポートしていない形式が多く、エラーが報告されるという問題が見つかりました。
エラーメッセージは次のとおりです。

feign.codec.DecodeException: Error while extracting response for type [com.inforun.common.core.domain.R<java.util.List<com.inforun.common.base.domain.TTaskTime>>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "23:59:59": not a valid representation (error: Failed to parse Date value '23:59:59': Unparseable date: "23:59:59"); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "23:59:59": not a valid representation (error: Failed to parse Date value '23:59:59': Unparseable date: "23:59:59")
 at [Source: (PushbackInputStream); line: 1, column: 82] (through reference chain: com.inforun.common.core.domain.R["data"]->java.util.ArrayList[0]->com.inforun.common.base.domain.TTaskTime["endTime"])

必要なのは時刻と日付だけであり、変換するときに機能しません。インターネットの情報を確認したところ、jackson は以下の型のみをサポートしていることがわかりました

"yyyy-MM-dd'T'HH:mm:ss.SSSZ";

"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

"yyyy-MM-dd";

"EEE, dd MMM yyyy HH:mm:ss zzz";

long类型的时间戳

これらの型には明らかに私が渡した形式が含まれていないため、自分で解決策を見つけるしかありません。

1. アノテーションの解決策としては、単一のクラスにアノテーションを追加する方法がありますが、
ここに画像の説明を挿入
この方法は少数にしか使えず、数が多い場合は一つずつ追加するのが面倒なので、この方法は使用しませんでした。

2. カスタム型コンバーターの方法
カスタムの時間型コンバーターを作成し、その時間型コンバーターを使用して必要な形式を変換できるため、注釈を 1 つずつ追加する必要がなく、より便利です。

import cn.hutool.core.date.DateUtil;

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");
    private SimpleDateFormat format2 = new SimpleDateFormat("yyy-MM-dd");
    private SimpleDateFormat format3 = new SimpleDateFormat("HH:mm:ss");

    public MyDateFormat(DateFormat dateFormat) {
    
    
        this.dateFormat = dateFormat;
    }

    @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 {
    
    
            // 先按我的规则1来
            date = format1.parse(source, pos);
        } catch (Exception e) {
    
    
            //方式1不行方式2
            try {
    
    
                date = format2.parse(source, pos);
            } catch (Exception e1) {
    
    
                //方式2不行方式3
                try {
    
    
                    date = format3.parse(source, pos);
                } catch (Exception e2) {
    
    
                    // 不行,那就按原先的规则吧
                    date = dateFormat.parse(source, pos);
                }
            }
        }
        return date;
    }    // 主要还是装饰这个方法

    @Override
    public Date parse(String source) throws ParseException {
    
    
        Date date = null;
        try {
    
    
            //先按照自己的规则来,动态筛查
            date = DateUtil.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);
    }
}

これはカスタム変換クラスです。実際、まだ単一の変換を使用しています。ここでは単一の変換に Hutool ツール クラスを使用しました。一般的に使用される時間タイプを自動的に識別できるため、手間を省くことができます。設定してみましょう。

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.inforun.common.security.config.jackson.MyDateFormat;
import com.inforun.common.security.interceptor.HeaderInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.text.DateFormat;

public class WebMvcConfig implements WebMvcConfigurer
{
    
    

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
    
    

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        //添加此配置
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        converter.setObjectMapper(objectMapper);
        DateFormat dateFormat = objectMapper.getDateFormat();
        objectMapper.setDateFormat(new MyDateFormat(dateFormat));
        return converter;
    }
}

ここまで完了していても、再度変換する場合は問題ありませんので、ぜひ試してみてください。

おすすめ

転載: blog.csdn.net/qq_45699784/article/details/131044965