You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3.0迁3.3时Jackson FAIL_ON_TRAILING_TOKENS异常问题

问题描述

将Spring Boot应用从3.0迁移至3.3版本后,自定义MultiDateDeserializer抛出FAIL_ON_TRAILING_TOKENS异常,尽管已显式配置ObjectMapper禁用该特性,且调试确认使用的是同一个ObjectMapper实例。

配置代码

@Bean
public Module dateSerializationModule() {
    return new SimpleModule("dateFormat")
        .addDeserializer(Date.class, new MultiDateDeserializer()).addSerializer(Date.class, new DateSerializer());
}

@Bean
@Primary
public ObjectMapper mapper() {
    return new ObjectMapper()
        .findAndRegisterModules().registerModule(attributesModule()).registerModule(dateSerializationModule())
        .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, false)
        .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
}

异常信息

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Trailing token (of type FIELD_NAME) found after value (bound as com.fasterxml.jackson.databind.JsonNode): not allowed as per DeserializationFeature.FAIL_ON_TRAILING_TOKENS

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Trailing token (of type FIELD_NAME) found after value (bound as com.fasterxml.jackson.databind.JsonNode): not allowed as per DeserializationFeature.FAIL_ON_TRAILING_TOKENS at [Source: REDACTED (StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION disabled); line: 1, column: 11847] (through reference chain: my.dto.MyDTO["aDateField"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) ~[jackson-databind-2.17.1.jar:2.17.1]
at com.fasterxml.jackson.databind.DeserializationContext.reportTrailingTokens(DeserializationContext.java:1840) ~[jackson-databind-2.17.1.jar:2.17.1]
at com.fasterxml.jackson.databind.ObjectMapper._verifyNoTrailingTokens(ObjectMapper.java:5013) ~[jackson-databind-2.17.1.jar:2.17.1]
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4886) ~[jackson-databind-2.17.1.jar:2.17.1]
at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3145) ~[jackson-databind-2.17.1.jar:2.17.1]
at my.app.MultiDateDeserializer.deserialize(MultiDateDeserializer.java:41) ~[main/:na]

自定义反序列化器代码

public class MultiDateDeserializer extends StdDeserializer<Date> {
    public MultiDateDeserializer() {
        this(null);
    }

    public MultiDateDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonNode node = jp.getCodec().readTree(jp);  // 异常抛出位置
        // ... 日期解析逻辑
    }
}

对应JSON字段

aDateField: "2022-03-09T00:00:00.000"

问题分析与解决方案

核心原因

Jackson 2.17(Spring Boot 3.3默认依赖版本)对readTree方法的尾随token检查逻辑进行了强化:在字段级反序列化器中调用readTree(jp)时,该方法会读取当前字段的value节点,随后检查整个JSON流是否还有未处理的token(比如DTO的其他字段),此时会判定为“尾随token”并触发异常。而Jackson 2.14版本中无此严格检查。

解决方案

修改自定义反序列化器,直接读取当前字段的value,无需通过readTree转换为JsonNode:

@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    // 直接读取日期字符串
    String dateStr = jp.getValueAsString();
    // 执行你的日期解析逻辑(比如兼容多种格式)
    if (dateStr == null || dateStr.isEmpty()) {
        return null;
    }
    // 示例:使用DateTimeFormatter解析ISO格式日期
    DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
    LocalDateTime localDateTime = LocalDateTime.parse(dateStr, formatter);
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}

备选方案(不推荐)

若必须保留readTree的使用方式,可通过DeserializationContext临时禁用该检查,但会破坏全局配置一致性:

@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
    // 临时禁用尾随token检查
    DeserializationContext modifiedContext = ctxt.with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, false);
    JsonNode node = modifiedContext.readValue(jp, JsonNode.class);
    // ... 后续日期解析逻辑
}

内容的提问来源于stack exchange,提问作者alvinmeimoun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 09:40:58