我试图使用Quarkus开发Rest API,仅从POST有效负载的数据生成PDF。只有当应用程序在本机模式下运行时,我才会出现以下异常:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [simple type, class java.math.BigDecimal]
at [Source: (SequenceInputStream); line: 1, column: 1]
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589)
at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:599)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:168)
at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:499)
at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:248)
at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:650)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findNonContextualValueDeserializer(DeserializationContext.java:466)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:473)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:476)
at com.fasterxml.jackson.databind.ObjectReader._findRootDeserializer(ObjectReader.java:2050)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1677)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:977)
at org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider.readFrom(ResteasyJackson2Provider.java:191)
at org.jboss.resteasy.plugins.providers.multipart.MultipartInputImpl$PartImpl.getBody(MultipartInputImpl.java:218)
at org.jboss.resteasy.plugins.providers.multipart.MultipartFormAnnotationReader.setFields(MultipartFormAnnotationReader.java:189)
at org.jboss.resteasy.plugins.providers.multipart.MultipartFormAnnotationReader.readFrom(MultipartFormAnnotationReader.java:79)
at org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext.readFrom(AbstractReaderInterceptorContext.java:101)
at org.jboss.resteasy.core.interception.jaxrs.ServerReaderInterceptorContext.readFrom(ServerReaderInterceptorContext.java:63)
at org.jboss.resteasy.core.interception.jaxrs.AbstractReaderInterceptorContext.proceed(AbstractReaderInterceptorContext.java:80)
at org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:213)
at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:95)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:128)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:621)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:487)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:437)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:439)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:400)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:374)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:67)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:488)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:259)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:160)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:163)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:245)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:122)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.access$000(VertxRequestHandler.java:36)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:87)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2027)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1551)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1442)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at java.lang.Thread.run(Thread.java:834)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:497)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:193)
我的数据如下:
@Getter
@Setter
public class Invoice {
@NotBlank
private String number;
@NotNull
private LocalDate date;
@NotNull
private Currency currency;
@NotNull
@AllowedLocale
private Locale locale;
@NotNull
@Valid
private Provider provider;
@NotNull
@Valid
private Customer customer;
@NotNull
@Valid
private Order order;
@Valid
private ConsolidatedTaxes consolidatedTaxes;
@NotNull
@Valid
private PaymentInstructions paymentInstructions;
}
一些嵌入式对象具有BigDecimal键映射:
@Getter
@Setter
public class ConsolidatedTaxes {
@NotNull
@Size(min = 1)
@Valid
private Map<BigDecimal, ValueAddedTax> byAmount;
@NotNull
@Valid
private ValueAddedTax total;
}
还有一些直接使用BigDecimal:
@Getter
@Setter
public class ValueAddedTax {
@NotNull
private BigDecimal baseAmount;
@NotNull
private BigDecimal taxAmount;
@NotNull
private BigDecimal includingTaxAmount;
}
我的依赖项:
<quarkus.version>1.3.2.Final</quarkus.version>
<lombok.version>1.18.12</lombok.version>
我真的不明白什么对象有反序列化的问题。当它在开发模式下运行时,问题不会附加。
我如何进行反序列化:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
</dependency>
@Path("/v1/invoices")
public class InvoiceController {
private InvoiceService invoiceService;
InvoiceController(InvoiceService invoiceService) {
this.invoiceService = invoiceService;
}
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("application/pdf")
public Response post(@MultipartForm InvoiceResource invoiceMultipartBody) throws IOException {
if (Objects.nonNull(invoiceMultipartBody.getLogo())) {
byte[] logo = invoiceMultipartBody.getLogo().readAllBytes();
invoiceMultipartBody.getInvoice().getProvider().setLogo(logo);
}
Response.ResponseBuilder response = Response.ok(invoiceService.generate(invoiceMultipartBody.getInvoice()));
response.header("Content-Disposition", "attachment; filename=" + invoiceMultipartBody.getInvoice().getNumber() + ".pdf");
return response.build();
}
}
@Getter
@Setter
public class InvoiceResource {
@FormParam("logo")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
public InputStream logo;
@FormParam("invoice")
@PartType(MediaType.APPLICATION_JSON)
public Invoice invoice;
}
JSON负载示例:
{
"number": "#Invoice-Number",
"date": "2019-06-25",
"currency": "EUR",
"locale": "fr_FR",
"provider": {
"corporateName": "corporateName",
"address": {
"identification": "identificationAddressSender"
}
},
"customer": {
"address": {
"identification": "identificationAddressRecipient"
}
},
"order" : {
"description": "description with accents special caracters &é'(§è!çà)-""
},
"paymentInstructions": {
"amount": 1386.26,
"dueDate": "2019-07-25"
}
}
什么是只有在本机编译期间才能产生这种kinf行为的append?谢谢你的帮助。
问题中有一个解决方案:github.com/quarkusio/quarkus/issues/8996
@RegisterForReflection(targets={xxx.class,BigDecimal.class}(
这听起来像是一个quarkus错误,你能解决一个问题吗?并@提到stuartwdouglas,我将尝试修复即将发布的下一个次要版本。