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

已注册JodaModule仍无法序列化org.joda.time.Days的问题求助

问题:Joda Time的Days类型无法被Jackson序列化

环境依赖

使用Joda Time 2.10.14与Jackson2 2.18.3,依赖如下:

jackson-core-2.18.3.jar
jackson-databind-2.18.3.jar
jackson-datatype-joda-2.18.3.jar
joda-time-2.10.14.jar

复现代码

已注册JodaModule但仍抛出序列化异常,代码示例:

public static void main(String[] args) throws JsonProcessingException {
    DateTime dateTime = new DateTime();
    Days days = Days.days(1);
    Map<String, Object> map = new HashMap<>();
    map.put("dateTime", dateTime);
    map.put("days", days);
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JodaModule());
    String json = objectMapper.writeValueAsString(map);
    System.out.println(json);
}

异常信息

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Joda date/time type `org.joda.time.Days` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-joda" to enable handling (through reference chain: java.util.HashMap["days"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1340)
at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:808)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:764)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:720)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:35)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:502)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:341)
at com.fasterxml.jackson.databind.ObjectMapper._writeValueAndClose(ObjectMapper.java:4819)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:4060)
at azkaban.utils.JSONUtils.main(JSONUtils.java:96)

经查看JodaModule源码,确认其未内置Days类型的序列化器,可通过以下方式解决:


解决方案

方案1:自定义序列化/反序列化器

针对Days类型编写专属的序列化和反序列化逻辑,注册到ObjectMapper:

// 序列化器:将Days转为整数
public class DaysSerializer extends JsonSerializer<Days> {
    @Override
    public void serialize(Days days, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeNumber(days.getDays());
    }
}

// 反序列化器:从整数还原为Days
public class DaysDeserializer extends JsonDeserializer<Days> {
    @Override
    public Days deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        return Days.days(p.getIntValue());
    }
}

注册到ObjectMapper:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JodaModule());

SimpleModule daysModule = new SimpleModule();
daysModule.addSerializer(Days.class, new DaysSerializer());
daysModule.addDeserializer(Days.class, new DaysDeserializer());
objectMapper.registerModule(daysModule);

方案2:手动转换为基础类型(仅序列化场景)

如果只需要序列化,无需反序列化,可在存入Map前直接将Days转为整数:

map.put("days", days.getDays());

方案3:使用Jackson Mixin特性

通过Mixin为Days类添加序列化注解,指定用getDays()方法的返回值作为序列化结果:

public abstract class DaysMixin {
    @JsonValue
    public abstract int getDays();
}

注册Mixin到ObjectMapper:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JodaModule());
objectMapper.addMixIn(Days.class, DaysMixin.class);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:42:35