Quarkus Jackson InvalidDefinitionException找不到类型[简单类型,类java.math.BigDecimal]的(Map)密钥反序列化器

问题描述 投票:1回答:2

我试图使用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;

}

某些嵌入式对象的Map具有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"
    }
}

仅在可以产生这种行为的本机编译期间追加什么?谢谢您的帮助。

jackson lombok quarkus
2个回答
0
投票

这听起来像是夸夸其谈的错误,您能解决一个问题和@mention stuartwdouglas吗,我将设法解决下一个未成年人的问题,该问题将很快发布。


0
投票

存在问题的解决方案:github.com/quarkusio/quarkus/issues/8996

@@ RegisterForReflection(targets = {xxx.class,BigDecimal.class})

© www.soinside.com 2019 - 2024. All rights reserved.