flinksql 解析kafka复杂嵌套json

flinksql 解析kafka复杂嵌套json

解析复杂json

JSON数据

{
    "afterColumns":{
        "created":"1589186680",
        "extra":{
            "canGiving":false
        },
        "parameter":[
            1,
            2,
            3,
            4
        ]
    },
    "beforeColumns":null,
    "tableVersion":{
        "binlogFile":null,
        "binlogPosition":0,
        "version":0
    },
    "touchTime":1589186680591
}

JSON数据类型和FLINK SQL数据类型的映射关系
在这里插入图片描述
sql代码

首先我们的JSON最外层是个OBJECT对象,有4个字段分别是afterColumns,beforeColumns,tableVersion,touchTime。其中afterColumns又是个嵌套JSON,也就是OBJECT对象;beforeColumns是个STRING类型;tableVersion同样也是个嵌套JSON;touchTime是number类型。所以我们最开始的DDL是这样的
	CREATE TABLE t1 ( 
	afterColumns ROW(),
	beforeColumns STRING,
	tableVersion ROW(),
	touchTime BIGINT
	)WITH (
    'connector.type' = 'kafka',  -- 指定连接类型是kafka
    'connector.version' = '0.11',  -- 与我们之前Docker安装的kafka版本要一致
    'connector.topic' = 'json_parse', -- 之前创建的topic 
    'connector.properties.group.id' = 'flink-test-0', -- 消费者组,相关概念可自行百度
    'connector.startup-mode' = 'earliest-offset',  --指定从最早消费
    'connector.properties.zookeeper.connect' = 'localhost:2181',  -- zk地址
    'connector.properties.bootstrap.servers' = 'localhost:9092',  -- broker地址
    'format.type' = 'json'  -- json格式,和topic中的消息格式保持一致
	) 		
		
 用FLINK SQL执行 select * from t1 看看,得到的结果是 ,null,,1589186680591
 afterColumns 和 tableVersion 都是空,另外两个字段都打印出来了,原因是afterColumns 和 tableVersion都是OBJECT类型,FLINK SQL还是没法帮我们智能识别出来,所以只能自己定义的更详细点。
 afterColumns中有三个字段,分别是created,extra,parameter,对应着STRING,OBJECT,ARRAY类型;extra中有一个字段canGiving,类型是BOOLEAN。
 tableVersion中也有三个字段,分别是binlogFile,binlogPosition,version,都是简单类型,分别是STRING,INTEGER,INTEGER。
 所以,我们新的DDL语句时这样的
	 CREATE TABLE t1 ( 
	afterColumns ROW(created STRING,extra ROW(canGiving BOOLEAN),`parameter` ARRAY <INT>) ,
	beforeColumns STRING ,
	tableVersion ROW(binlogFile STRING,binlogPosition INT ,version INT) ,
	touchTime bigint 
	) WITH (
	    'connector.type' = 'kafka',  -- 指定连接类型是kafka
	    'connector.version' = '0.11',  -- 与我们之前Docker安装的kafka版本要一致
	    'connector.topic' = 'json_parse', -- 之前创建的topic 
	    'connector.properties.group.id' = 'flink-test-0', -- 消费者组,相关概念可自行百度
	    'connector.startup-mode' = 'earliest-offset',  --指定从最早消费
	    'connector.properties.zookeeper.connect' = 'localhost:2181',  -- zk地址
	    'connector.properties.bootstrap.servers' = 'localhost:9092',  -- broker地址
	    'format.type' = 'json'  -- json格式,和topic中的消息格式保持一致
	)
	这里我们注意一下,parameter得用``括起来,因为parameter是个关键字,想用的话得用``包围,所有关键字可以参考https://ci.apache.org/projects/flink/flink-docs-release-1.10/dev/table/sql/#reserved-keywords
	最后输出的数据是这样的:1589186680,false,[1, 2, 3, 4],null,null,0,0,1589186680591,和我们JSON中的数据一样,没毛病!
	不过我们用的是select *,正常来说我们应该只输出想要的字段。那么,假设我们只想拿到canGiving 这个嵌套好几层的字段值,该怎么写呢?
	其实很简单,就像是包路径一样 afterColumns.extra.canGiving ,试一下
	select  afterColumns.extra.canGiving from t1
	输出:false
	再试一下输出 parameter 这个集合的第一个值
	select afterColumns.`parameter`[0] from t1
	报错了:Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
  很纳闷,长度为4的数组,取数组序号为0,也就是数组中第一个数,竟然报角标越界了,换成afterColumns.`parameter`[1]试试看呢?
  震惊!竟然输出了1,也就是我们数组中的第一个字段。可在我们JAVA应用或者HIVE SQL中,数组不是应该是从0开始吗?
  因为 Flink 中数组下标是从 1 开始的,在 Validation 阶段发现下标是小于等于 0 的时候抛出异常
要消费Kafka中的复杂JSON数据,可以使用Apache FlinkJSON解析库来解析JSON数据。首先,在Flink中,需要使用Kafka Consumer来消费Kafka中的消息。然后,可以使用FlinkJSON解析库来解析JSON数据,将其转换为Flink中的数据类型。最后,可以对数据进行处理和转换,并将结果发送回Kafka或其他存储系统。 以下是一个使用Flink消费Kafka中的JSON数据的示例程序: ```java // 创建一个Kafka Consumer FlinkKafkaConsumer<String> kafkaConsumer = new FlinkKafkaConsumer<>("topic-name", new SimpleStringSchema(), properties); // 从Kafka中读取JSON数据 DataStream<String> jsonStream = env.addSource(kafkaConsumer); // 解析JSON数据为Flink中的数据类型 DataStream<MyData> myDataStream = jsonStream.map(new MapFunction<String, MyData>() { @Override public MyData map(String jsonString) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); MyData myData = objectMapper.readValue(jsonString, MyData.class); return myData; } }); // 对数据进行处理和转换 DataStream<MyResult> myResultStream = myDataStream.filter(new FilterFunction<MyData>() { @Override public boolean filter(MyData myData) throws Exception { return myData.value > 0; } }).map(new MapFunction<MyData, MyResult>() { @Override public MyResult map(MyData myData) throws Exception { return new MyResult(myData.key, myData.value * 2); } }); // 将结果发送回Kafka或其他存储系统 FlinkKafkaProducer<MyResult> kafkaProducer = new FlinkKafkaProducer<>("result-topic", new MyResultSchema(), properties); myResultStream.addSink(kafkaProducer); ``` 在上面的示例程序中,MyData和MyResult是自定义的数据类型,可以根据实际需求进行定义。MyData表示从Kafka中读取的JSON数据,MyResult表示处理后的结果数据。 在map函数中,使用Jackson JSON解析库将JSON字符串解析为MyData类型的对象。然后,在filter和map函数中对数据进行处理和转换,生成MyResult类型的对象。最后,使用FlinkKafkaProducer将结果发送回Kafka或其他存储系统。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值