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

Quarkus中Jackson无法反序列化GeoLatte Geometry的问题

问题: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 19:20:47