JsonParseException: 意外字符 ('i' (代码 105)):预期是双引号

3
我正在尝试集成Spring Cloud Streams,并使用RabbitMQ作为代理在服务之间发布自定义Java对象。我要发布的对象如下:
public class AppMessageEnvelope implements Serializable {
  ...
  private Object messageBody;
  private Date sentAt = new Date();
  ...

  // setters and getters
}

这只是一个包装对象,原始对象被放置在messageBody中。我放在messageBody中的对象看起来像:
public class Job {
    ...
    private String message;
    private Map<MyEnum, String> myMap;
    ...
}

请注意,AppMessageEnvelopeJob都在一个不同的模型项目中,该项目作为Maven依赖项导入发布者和订阅者Spring Boot项目中,因此模型完全相同。

在生产者中,我将对象发布为:

@EnableBinding(Source.class)
public class JobDistributor {

    private final Source jobQueue;

    @Autowired
    public JobDistributor(Source jobQueue) {
        this.jobQueue = jobQueue;
    }

    public AppMessageEnvelope publishJob(AppMessageEnvelope message) {
        LOG.info("Sending message: {}.", message);
        jobQueue.output().send(MessageBuilder.withPayload(message).build());
        return message;
    }
}

在消费者端,我收到了以下信息:
@Component
@EnableBinding(Sink.class)
public class JobConsumer {

    private final JobManager jobManager;
    private final ObjectMapper objectMapper;

    @Autowired
    public JobConsumer(
            JobManager jobManager, ObjectMapper objectMapper) {
        this.jobManager = jobManager;
        this.objectMapper = objectMapper;
    }

    @StreamListener(target = Sink.INPUT)
    public void processData(AppMessageEnvelope messageEnvelope) {
        LOG.info("Envelope received: {}.", messageEnvelope);

        try {
            TypeReference<Job> mapType = new TypeReference<Job>() {};
            Job job = objectMapper.readValue(messageEnvelope.getMessageBody().toString(), mapType);
            jobManager.processRequest(job);
        } catch (Exception ex) {
            LOG.error("Couldn't convert to correct object for processing: {}.", ex);
        }
    }
}

我尝试使用TypeReference将内部对象转换为正确的对象,但是我收到了以下错误提示:
JobConsumer - Couldn't convert to correct object for processing: {}.
    com.fasterxml.jackson.core.JsonParseException: Unexpected character ('i' (code 105)): was expecting double-quote to start field name
    at [Source: (StringReader); line: 1, column: 3]

在消息转换之前,我会记录它:
JobConsumer - Envelope received: AppMessageEnvelope{..., messageBody={id=5bf3a7302dbe9c7cf9927c60, jobId=8c0bfcb0b21248e694b5cd52337a1f9e, submittedAt=2018-11-20T06:18:24+0000, lastUpdatedOn=null, message=null, ..., fileContentMap={FILE_BYTES=JVBERi0xLjUKJb/3ov}}, sentAt=Tue Nov 20 11:48:24 IST 2018}

我尝试将ObjectMapper配置为:
@Autowired
private ObjectMapper objectMapper() {
    JsonFactory factory = new JsonFactory();
    factory.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
    return new ObjectMapper(factory);
}

我尝试使用以下方式启用取消引用字段:
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

我尝试了这篇博客和一些类似的SO问题提供的解决方案,但都没有解决。我错过了什么吗?

1
你能否尝试以下代码:return new ObjectMapper().configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); - Raheela Aslam
抱歉,我错过了这个。我也尝试过这个。让我把这个加到 OP 中。 - Shubham A.
请确认您的JSON是否有效。还请查看https://dev59.com/WW445IYBdhLWcg3wg6xn。 - Raheela Aslam
当您打印 messageEnvelope.getMessageBody().toString()messageEnvelope.getMessageBody().getClass() 时,会打印什么内容? - JB Nizet
正如之前所建议的,问题似乎出现在messageEnvelope.getMessageBody().toString()这里。你假设它会给出一个JSON字符串。(错误也指出了同样的问题,即JSON属性没有以")"开头)。你能打印这个值并验证一下吗? 此外,你可以使用ObjectMapper从messageEnvelope.getMessageBody()获取一个JSON字符串,然后将其映射到所需的pojo上。 - RaRa
显示剩余2条评论
3个回答

2
使用以下 JSON 转换将 JSON 转换为模型/实体。
ObjectMapper objectMapper = new ObjectMapper();
Job job = objectMapper.convertValue(messageEnvelope.getMessageBody().toString(), Job.class);

0
这可能是一个有趣的错误,请复制您的 JSON 并粘贴到在线 JSON 格式化器 中。如果验证失败,请手动重写 JSON 或对其进行编码。
错误原因:复制自各种来源时存在字符编码问题。

0
这里是问题: Job job = objectMapper.readValue(messageEnvelope.getMessageBody().toString(), mapType); 像这样: Job job = objectMapper.readValue(objectMapper.writeValueAsString(messageEnvelope.getMessageBody()), mapType);

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - kerbermeister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接