Spring Kafka消费者反序列化报cannot deserialize错误
报错原因
cannot deserialize from Object value (no delegate- or property-based Creator)是Jackson反序列化时找不到合法对象创建入口抛出的异常,具体触发逻辑:
- 你编写的
Payload实体类只定义了全参构造方法,Java语法规则下,只要类中显式定义了任意构造函数,JVM就不会自动生成无参构造 - Spring Kafka集成的
JsonDeserializer默认走无参实例化+setter赋值的反序列化流程,没有无参构造时无法创建Payload实例,直接抛出异常。
修复方案
任选以下一种方式修改即可解决问题:
- 方案1:为
Payload类添加无参构造函数,改动最小,原有逻辑不需要调整。修改后的Payload类代码如下:
public class Payload { private List<JsonNode> fields; private String name; private String type; // 新增无参构造,供Jackson反序列化时实例化对象 public Payload() { } public Payload(List<JsonNode> fields, String name, String type) { this.fields = fields; this.name = name; this.type = type; } public List<JsonNode> getFields() { return fields; } public void setFields(List<JsonNode> fields) { this.fields = fields; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
- 方案2:如果不想保留无参构造,可以通过Jackson注解指定全参构造为反序列化入口,在构造方法和参数上添加对应注解即可:
public class Payload { private List<JsonNode> fields; private String name; private String type; @JsonCreator public Payload( @JsonProperty("fields") List<JsonNode> fields, @JsonProperty("name") String name, @JsonProperty("type") String type) { this.fields = fields; this.name = name; this.type = type; } // 原有getter、setter方法保持不变 public List<JsonNode> getFields() { return fields; } public void setFields(List<JsonNode> fields) { this.fields = fields; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
注意:使用该方案需要确保项目中已经引入Jackson的annotation依赖,Spring Boot生态下默认会随spring-kafka自动引入,不需要额外添加。
- 方案3:如果不需要对消息字段做强类型绑定,直接使用Jackson原生的
JsonNode作为消费值类型即可,省去自定义实体类的步骤,对应修改消费者配置:
@EnableKafka @Configuration public class KafkaStreamReaderConfig { @Bean public ConsumerFactory<String, JsonNode> consumerFactory(){ Map<String,Object> config = new HashMap<>(); config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"localhost:9092"); config.put(ConsumerConfig.GROUP_ID_CONFIG, "groupId"); config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class); return new DefaultKafkaConsumerFactory<>(config, new StringDeserializer(), new JsonDeserializer<>(JsonNode.class)); } @Bean public ConcurrentKafkaListenerContainerFactory<String, JsonNode> kafkaListener(){ ConcurrentKafkaListenerContainerFactory<String, JsonNode> factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); return factory; } }
补充:原配置中ConcurrentKafkaListenerContainerFactory没有指定泛型,属于原生类型使用,会产生编译警告,补上对应泛型参数即可。
内容的提问来源于stack exchange,提问作者Nimasha Fernando
相关产品推荐
相关产品推荐

