JAX-RS序列化异常:FinalScoreResponse中finalScores无法序列化
JAX-RS接口JSON序列化失败问题解决
错误日志
2024-10-23 12:21:14,135 SEVERE [org.ecl.yas.int.SerializationContextImpl] (executor-thread-3) Generating incomplete JSON 2024-10-23 12:21:14,136 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-3) HTTP Request to /api/contacts/scores/compound/gambit-digital.com failed, error id: 971b0a13-4991-45ff-b720-dfb50644855f-20: jakarta.json.bind.JsonbException: Unable to serialize property 'finalScores' from at.hksolutions.gambit.boundary.jaxrs.FinalScoreResponse
相关代码
JAX-RS接口代码
@GET @Path("mypath") @Produces(MediaType.APPLICATION_JSON) public FinalScoreResponse getFinalScores() { // 业务逻辑 return new FinalScoreResponse(finalScores, cache.lastUpdated); }
FinalScoreResponse 定义
public record FinalScoreResponse( List<FinalScore> finalScores, Date lastUpdated ) { }
FinalScore 定义
public record FinalScore( String id, String name, double score, int normalizedScore, String lifecycleStage ) { }
已排查情况
- 当FinalScoreResponse仅包含
lastUpdated字段时,序列化正常 - 接口直接返回
List<FinalScore>时,序列化正常
解决方案
方案1:为FinalScoreResponse添加Jsonb注解显式指定序列化字段
在FinalScoreResponse的字段上添加@JsonbProperty注解,明确告知JSON-B需要序列化的属性:
public record FinalScoreResponse( @JsonbProperty("finalScores") List<FinalScore> finalScores, @JsonbProperty("lastUpdated") Date lastUpdated ) { }
方案2:检查JSON-B实现版本与Quarkus兼容性
当前使用Quarkus环境,需确保JSON-B依赖(如Eclipse Yasson)版本与Quarkus版本匹配。可在pom.xml中锁定兼容版本:
<dependency> <groupId>org.eclipse</groupId> <artifactId>yasson</artifactId> <version>2.0.4</version> <!-- 替换为与Quarkus匹配的版本 --> </dependency>
方案3:手动实现序列化逻辑
若上述方案无效,可在接口中手动将FinalScoreResponse序列化为JSON字符串返回:
@GET @Path("mypath") @Produces(MediaType.APPLICATION_JSON) public String getFinalScores() throws JsonbException { FinalScoreResponse response = new FinalScoreResponse(finalScores, cache.lastUpdated); Jsonb jsonb = JsonbBuilder.create(); return jsonb.toJson(response); }
方案4:替换Date字段为LocalDateTime
java.util.Date在JSON-B序列化中可能存在兼容性问题,将lastUpdated字段替换为java.time.LocalDateTime:
public record FinalScoreResponse( List<FinalScore> finalScores, LocalDateTime lastUpdated ) { }
同时在业务逻辑中将cache.lastUpdated转换为LocalDateTime类型。
内容的提问来源于stack exchange,提问作者Josip Domazet
相关产品推荐
相关产品推荐

