Java Flink反序列化Kafka JSON

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

我正试图与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.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之前如何序列化值?python3
confluent\u Kafka
producer with
json.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);
    }
}