将Kafka有效负载转换为对象

时间:2020-01-18 16:15:13

标签: java spring spring-boot spring-kafka

我对卡夫卡中的反序列化有一个疑问。

我的kafka应用程序中收到了这个字符串

Payload: {"post":{"postId":"5e22fac7f7356803e8784172","tags":["a","lovve","asldkjfsbajfdkjlnzx","z"]},"date":"2020-01-18T16:12:50.833423","user":{"userId":"5dfcfd77367c690edd91b2d9"},"reactionType":"unloved"}

我的kafka中有此配置

@Bean
public Map<String, Object> consumerConfigs() {
    Map<String, Object> props = new HashMap<>(
            kafkaProperties.buildConsumerProperties());

    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
            StringDeserializer.class);
    props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
            JsonDeserializer.class);
    props.put(ConsumerConfig.GROUP_ID_CONFIG,
            "magpie-trending");
    props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");

    return props;
}

我有一个具有与有效负载相同代码的类,以及如何在任何时候在对象中进行转换?

所以我也有这种方法

大家好,我有一个微服务接收到此字符串并且正在工作,但是我需要将此字符串转换为一个特定的对象,并且当我使用ObjectMapper进行转换时,应用程序返回此异常:

抛出异常;嵌套异常为 com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法 构造的实例 com.avenuecode.magpie.trending.component.kafka.message.PostMessage (不存在像默认构造一样的创建者):无法从中反序列化 对象值(没有基于委托或属性的创建者)

所以我的对象是:

public class ReactionMessage {
 private PostMessage post;
 private String date;
 private UserMessage user;
 private String reactionType;

 @JsonCreator
 public ReactionMessage(@JsonProperty("post") PostMessage post,
                       @JsonProperty("user") UserMessage user,
                       @JsonProperty("date") String date,
                       @JsonProperty("reactionType") String reactionType) {
    this.post = post;
    this.date = date;
    this.user = user;
    this.reactionType = reactionType;
 }

 @JsonCreator
 public ReactionMessage() {
 }
}

当我调用映射器时,就是在这种方法中

  @KafkaListener(topics = "reaction-topic", clientIdPrefix = "string", groupId = "magpie-trending")
  public void listenAsObject(ConsumerRecord<String, String> cr,
                           @Payload String payload) throws IOException {
    logger.info("Logger 1 [JSON] received key {}: Type [{}] | Payload: {} | Record: {}", cr.key(),
            typeIdHeader(cr.headers()), payload, cr.toString());

    ObjectMapper mapper = new ObjectMapper();
    ReactionMessage message = mapper.readValue(payload, ReactionMessage.class);

}

   private static String typeIdHeader(Headers headers) {
    return StreamSupport.stream(headers.spliterator(), false)
            .filter(header -> header.key().equals("__TypeId__"))
            .findFirst().map(header -> new String(header.value())).orElse("N/A");
}

1 个答案:

答案 0 :(得分:2)

您需要使JsonDeserializer返回您期望的对象类型

例如,Kafka内置的JSON解串器仅返回JsonNode

Spring JSON反序列化器具有额外的属性以传递类名

Kafka - Deserializing the object in Consumer