Quarkus中MicroProfile REST Client自定义Jackson序列化器未触发
问题描述
在Quarkus中使用MicroProfile REST Client,已引入quarkus-rest-client-reactive-jackson依赖。自定义了继承StdSerializer的HighlightSerializer序列化器,并通过ObjectMapperCustomizer完成注册,但调用外部API时序列化器的serialize方法从未触发——仅序列化器构造方法和ObjectMapperCustomizer的customize方法正常执行。后续验证发现,相同序列化代码在Quarkus REST端点中可正常工作,仅REST Client调用外部API时失效。
相关代码
HighlightSerializer.java
public class HighlightSerializer extends StdSerializer<Highlight> { public HighlightSerializer() { this(null); System.out.println("constuctor"); } public HighlightSerializer(Class<Highlight> t) { super(t); System.out.println("constuctor"); } @Override public void serialize(Highlight value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException { System.out.println("serialize"); jsonGenerator.writeStringField("niklas", "niklas"); } }
RegisterCustomModuleCustomizer.java
@Singleton public class RegisterCustomModuleCustomizer implements ObjectMapperCustomizer { @Override public int priority() { return MINIMUM_PRIORITY; } public void customize(ObjectMapper mapper) { System.out.println("customize"); SimpleModule module = new SimpleModule(); module.addSerializer(Highlight.class, new HighlightSerializer()); mapper.registerModule(module); } }
问题根源
ObjectMapperCustomizer默认仅作用于Quarkus的JAX-RS端点的Jackson配置,而Quarkus REST Client Reactive拥有独立的Jackson处理流程,不会自动复用全局的ObjectMapperCustomizer配置,因此自定义序列化器未被应用到REST Client的序列化环节。
解决方案
针对REST Client Reactive单独配置Jackson自定义序列化器,有两种可行方式:
方式一:全局配置所有REST Client
创建实现JacksonRestClientBuilderCustomizer的类,为所有REST Client注册自定义序列化模块:
import io.quarkus.rest.client.reactive.jackson.JacksonRestClientBuilderCustomizer; import jakarta.inject.Singleton; import com.fasterxml.jackson.databind.module.SimpleModule; import org.eclipse.microprofile.rest.client.RestClientBuilder; @Singleton public class RestClientJacksonCustomizer implements JacksonRestClientBuilderCustomizer { @Override public void customize(RestClientBuilder builder, String configKey) { SimpleModule customModule = new SimpleModule(); customModule.addSerializer(Highlight.class, new HighlightSerializer()); // 为REST Client注册自定义模块 builder.register(customModule); } }
方式二:为单个REST Client配置
在目标REST Client接口上,通过@RegisterProvider注解直接注册序列化器或自定义模块:
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; @RegisterRestClient(baseUri = "你的外部API地址") @RegisterProvider(HighlightSerializer.class) public interface ExternalApiClient { @POST @Path("/target-endpoint") void sendHighlightRequest(Highlight highlight); }
如果需要注册多个序列化器/反序列化器,可先封装为自定义模块:
public class CustomJacksonModule extends SimpleModule { public CustomJacksonModule() { addSerializer(Highlight.class, new HighlightSerializer()); // 可添加其他序列化/反序列化器 } }
再在REST Client接口上注册该模块:
@RegisterRestClient(baseUri = "你的外部API地址") @RegisterProvider(CustomJacksonModule.class) public interface ExternalApiClient { // ...接口方法 }
验证
修改配置后重启应用,调用外部API时,HighlightSerializer的serialize方法将被触发,控制台会输出serialize日志,同时生成预期格式的JSON请求体。
内容的提问来源于stack exchange,提问作者Niklas Heidloff

