首页 > 解决方案 > 将 JSON 反序列化为类实例

问题描述

我有一个通过 RabbitMQ 作为消息发送的类,在发件人服务上,它的定义如下:

public final class User implements Serializable {

    private String nome;
    private String cognome;

    public User(@JsonProperty("nome") String nome,
                @JsonProperty("cognome") String cognome) {
        this.nome = nome;
        this.cognome = cognome;
    }

    public String getNome() {
        return nome;
    }

    public String getCognome() {
        return cognome;
    }

    public User(){}
}

在接收器服务上:

@Document
public class Persona {

    @Id
    @JsonProperty
    public ObjectId id;

    private String nome;

    private String cognome;

    public String getId() {
        return id.toHexString();
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getCognome() {
        return cognome;
    }

    public void setCognome(String cognome) {
        this.cognome = cognome;
    }

    public Persona(ObjectId id, String nome, String cognome) {
        this.id = id;
        this.nome = nome;
        this.cognome = cognome;
    }

    public Persona(){}
}

在接收器控制器中,我有以下方法,它应该接收该消息,将其转换为一个对象,并将其保存在数据库中,它看起来像:

@RabbitListener(queues = {"default_parser_q"})
    public void receiveMessage(final Message message){
        ObjectMapper mapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

        mapper.readValue(message.getBody(), Persona.class);
        System.out.println(message.toString() + "the message has been received");
    }

问题是我在该readValue()方法上遇到了异常,特别是:

未处理的异常:java.io.IOException、com.fasterxml.jackson.core.JsonParseException、com.fasterxml.jackson.databind.JsonMappingException

在这种情况下发送的消息(JSON)是:

{
  'nome': "John",
  'cognome': "Doe"
}

我在这里做错了什么?

编辑:根据要求添加堆栈跟踪。

com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造实例demo.com.fetcherservice.models.Persona (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{ "nome": "John", "cognome": "Doe" }') at [Source: (byte[])""{\n\t\t\t\"nome\": \"John\",\n\t\t\t\"cognome\": \"Doe\"\n\t\t}""; line: 1, column: 1] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343) at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032) at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371) at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3091) at kdmforce.com.fetcherservice.services.FetcherService.receiveMessage(FetcherService.java:23) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:50) at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:196) at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:129) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1552) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1478) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1466) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1461) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1410) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:870) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:854) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:78) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1137) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1043) at java.lang.Thread.run(Thread.java:748) com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of demo.com.fetcherservice.models.Persona(尽管至少存在一个 Creator):在 [Source: (byte[ ])""{\n\t\t\t\"nome\": \"John\",\n\t\t\t\"cognome\": \"Doe\"\n\t\t }""; line: 1, column: 1] at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63) at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343) at com .fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032) 在 com.fasterxml.jackson.databind.deser。

标签: javajacksonrabbitmqspring-rabbit

解决方案


它看起来像我在 Kafka 中看到的行为,因为您也在使用 Spring,我认为它是相同的。

您的发送端将对象转换为 Json,然后将其作为字符串发送 - 因此错误消息 ( \"nome\": \"John\",\n\t\t\t\"cognome\": \"Doe\") 中的转义引号。

您需要在发送方声明 JsonSerializer 然后将其传递给您的User, 或者 - 如果您手动创建 Json 字符串 - 声明它是一个字节数组,因此 Spring 不会尝试转义引号和空格。


推荐阅读