Quarkus中Jackson无法反序列化GeoLatte Geometry的问题
在Quarkus项目中尝试在DTO中使用GeoLatte的Geometry<C2D>类型,代码实现如下:
@Data @Accessors(chain = true) @RegisterForReflection public class TrackDTO { ... @JsonSerialize(using = GeometrySerializer.class) @JsonDeserialize(using = GeometryDeserializer.class) private Geometry<C2D> geom; ... }
同时创建了Jackson配置类注册GeoLatte模块:
@Singleton public class JacksonConfig implements ObjectMapperCustomizer { @Override public void customize(ObjectMapper objectMapper) { objectMapper.registerModule(new GeolatteGeomModule()); } }
但通过以下命令提交GeoJSON格式的Geometry数据时:
http http://localhost:8080/tracks \ geom:="{ \"type\": \"point\", \"coordinates\": [ 1, 1 ] }"
系统抛出反序列化错误:
2022-09-24 23:38:51,933 SEVERE [org.ecl.yas.int.Unmarshaller] (executor-thread-0) Unable to deserialize property 'geom' because of: Cannot create instance of a class: class org.geolatte.geom.Geometry, No default constructor found.
项目的build.gradle依赖如下:
dependencies { implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}") implementation 'io.quarkus:quarkus-smallrye-health' implementation 'io.quarkus:quarkus-resteasy-jsonb' implementation 'io.quarkus:quarkus-hibernate-orm-panache' implementation 'io.quarkus:quarkus-resteasy' implementation 'io.quarkus:quarkus-resteasy-jaxb' implementation 'io.quarkus:quarkus-resteasy-jackson' implementation 'io.quarkus:quarkus-spring-data-jpa' implementation 'io.quarkus:quarkus-jdbc-postgresql' implementation 'io.quarkus:quarkus-arc' implementation 'io.quarkus:quarkus-smallrye-openapi' testImplementation 'io.quarkus:quarkus-junit5' implementation 'com.github.fmcejudo:quarkus-eureka:0.0.14' implementation 'net.postgis:postgis-jdbc:2021.1.0' // implementation 'org.hibernate:hibernate-spatial:6.1.3.Final' implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4' implementation 'com.vladmihalcea:hibernate-types-55:2.19.2' implementation 'org.geolatte:geolatte-geom:1.8.2' implementation 'org.geolatte:geolatte-geojson:1.8.2' }
对应的Resource、Service及Mapper代码如下:
TrackResource:
@Resource @Path("/tracks") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public class TrackResource { @Inject TrackService trackService; @POST @Path("") public void saveTrack(TrackDTO trackDTO) { trackService.saveTrack(trackDTO); } }
TrackService:
@ApplicationScoped public class TrackService { private final TrackRepository trackRepository; private final TrackMapper trackMapper; public TrackService(TrackRepository trackRepository, TrackMapper trackMapper) { this.trackRepository = trackRepository; this.trackMapper = trackMapper; } public void saveTrack(TrackDTO trackDTO) { trackRepository.save(trackMapper.toEntity(trackDTO)); } }
TrackMapper:
@ApplicationScoped public class TrackMapper { public TrackDTO toDTO(Track track) { return new TrackDTO() .setId(track.getId()) .setGeom(track.getGeom()) ; } public List<TrackDTO> toDTO(List<Track> tracks) { return tracks.stream().map(this::toDTO).collect(java.util.stream.Collectors.toList()); } public Track toEntity(TrackDTO trackDTO) { return new Track() .setId(trackDTO.getId()) .setGeom(trackDTO.getGeom()) ; } public List<Track> toEntity(List<TrackDTO> trackDTOs) { return trackDTOs.stream().map(this::toEntity).collect(java.util.stream.Collectors.toList()); } }
1. 移除JSON-B依赖,避免序列化冲突
Quarkus中同时引入quarkus-resteasy-jsonb和quarkus-resteasy-jackson时,默认优先使用JSON-B处理序列化/反序列化,导致你配置的Jackson GeoLatte模块不生效。修改build.gradle,移除以下依赖:
implementation 'io.quarkus:quarkus-resteasy-jsonb'
2. 移除DTO中手动指定的序列化/反序列化器
GeolatteGeomModule已经内置了GeoJSON与GeoLatte Geometry的序列化/反序列化逻辑,无需手动添加@JsonSerialize和@JsonDeserialize注解,移除后让Jackson自动使用模块处理器:
@Data @Accessors(chain = true) @RegisterForReflection public class TrackDTO { ... private Geometry<C2D> geom; ... }
3. 使用具体的Geometry类型而非抽象类
Geometry<C2D>是抽象类,无默认构造函数,Jackson无法直接实例化。根据提交的GeoJSON类型(Point),改用具体实现类:
private Point<C2D> geom;
同时同步调整Entity和Mapper中的对应类型,保证类型一致。
4. 移除手动指定的Jackson版本,使用Quarkus平台管理版本
手动添加jackson-databind依赖易引发版本冲突,Quarkus平台已内置兼容版本,移除以下依赖:
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4'
5. 确保Jackson配置类生效
确认JacksonConfig被Quarkus正确扫描,可添加@Provider注解确保被JAX-RS上下文加载:
@Singleton @Provider public class JacksonConfig implements ObjectMapperCustomizer { @Override public void customize(ObjectMapper objectMapper) { objectMapper.registerModule(new GeolatteGeomModule()); } }
内容的提问来源于stack exchange,提问作者Kambei

