Java Flink反序列化Kafka JSON
我正试图与flink一起阅读来自卡夫卡主题的json消息 我正在使用卡夫卡2.4.1和Flink 1.10 对于我的消费者,我设置了:Java Flink反序列化Kafka JSON,java,json,apache-kafka,apache-flink,Java,Json,Apache Kafka,Apache Flink,我正试图与flink一起阅读来自卡夫卡主题的json消息 我正在使用卡夫卡2.4.1和Flink 1.10 对于我的消费者,我设置了: import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.util.serialization.JSONKeyValueDeserializationSchema; import org.apache.flink
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;
import org.apache.flink.streaming.util.serialization.JSONKeyValueDeserializationSchema;
import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode;
FlinkKafkaConsumer<ObjectNode> sensorConsumer = new FlinkKafkaConsumer(KAFKA_TOPIC_INPUT,
new JSONKeyValueDeserializationSchema(false), properties);
sensor_5
将是本主题中的一个关键点我猜我需要添加一些其他内容,以便从kafka消息值中获取JSON并以某种方式处理该关键点,但我不确定
有什么建议吗
json结构是:
{"value": 1.0, "timestamp": "2020-05-01 14:00:00.000000"}
并通过
# Python 3
import json
from confluent_kafka import Producer
dict_obj = {"value": 1.0, "timestamp": "2020-05-01 14:00:00.000000"}
producer = Producer({'bootstrap.servers': "kafka:9092"})
producer.produce(topic='sensors-raw', key='sensor_5', value=json.dumps(dict_obj))
因此,基本上,如果您查看
JSONKeyValueDeserializationSchema
的源代码,您可以看到它如下所示:
if (mapper == null) {
mapper = new ObjectMapper();
}
ObjectNode node = mapper.createObjectNode();
if (record.key() != null) {
node.set("key", mapper.readValue(record.key(), JsonNode.class));
}
if (record.value() != null) {
node.set("value", mapper.readValue(record.value(), JsonNode.class));
}
if (includeMetadata) {
node.putObject("metadata")
.put("offset", record.offset())
.put("topic", record.topic())
.put("partition", record.partition());
}
return node;
因此,通常模式希望您的密钥是JSON而不是字符串,因此对于
sensor_5
,它将失败。我认为最好、最简单的解决方案是创建自己的以字符串为键的实现。如果不想在记录中包含键,可以实现反序列化模式
,而不是KeyedDeserializationSchema
示例如下所示:
public class JSONValueDeserializationSchema implements DeserializationSchema<ObjectNode> {
private static final long serialVersionUID = -1L;
private ObjectMapper mapper;
@Override
public ObjectNode deserialize(byte[] message) throws IOException {
if (mapper == null) {
mapper = new ObjectMapper();
}
ObjectNode node = mapper.createObjectNode();
if (message != null) {
node.set("value", mapper.readValue(message, JsonNode.class));
}
return node;
}
@Override
public boolean isEndOfStream(ObjectNode nextElement) {
return false;
}
@Override
public TypeInformation<ObjectNode> getProducedType() {
return getForClass(ObjectNode.class);
}
}
公共类JSONValueDeserializationSchema实现反序列化Schema{
私有静态最终长serialVersionUID=-1L;
私有对象映射器映射器;
@凌驾
public ObjectNode反序列化(字节[]消息)引发IOException{
if(映射器==null){
映射器=新的ObjectMapper();
}
ObjectNode=mapper.createObjectNode();
如果(消息!=null){
set(“value”,mapper.readValue(message,JsonNode.class));
}
返回节点;
}
@凌驾
公共布尔值isEndOfStream(ObjectNode nextElement){
返回false;
}
@凌驾
公共类型信息getProducedType(){
返回getForClass(ObjectNode.class);
}
}
如果您还想在记录中包含密钥,可以实现Dominik Wosiński在回答中提到的
KeyedDeserializationSchema
。在进入Kafka之前如何序列化值?python3confluent\u Kafka
producer withjson.dumps(data\u dict)
。dict只是一个普通的python字典,它混合了字符串和具有不同键的浮点值。请您也发布JSON。所以我可以在我的电脑中重现这个问题?添加了完整的代码来生成消息,这是否意味着我必须使用org.apache.flink.streaming.connectors.kafka.KafkaDeserializationSchema
创建我自己的类,然后使用JSONKeyValueDeserializationSchema
作为这样就可以处理Kafka密钥和json消息了?
public class JSONValueDeserializationSchema implements DeserializationSchema<ObjectNode> {
private static final long serialVersionUID = -1L;
private ObjectMapper mapper;
@Override
public ObjectNode deserialize(byte[] message) throws IOException {
if (mapper == null) {
mapper = new ObjectMapper();
}
ObjectNode node = mapper.createObjectNode();
if (message != null) {
node.set("value", mapper.readValue(message, JsonNode.class));
}
return node;
}
@Override
public boolean isEndOfStream(ObjectNode nextElement) {
return false;
}
@Override
public TypeInformation<ObjectNode> getProducedType() {
return getForClass(ObjectNode.class);
}
}