前言
最近在数据接入的工作中,接入了两种json日志数据。它们只有一个字段名称不一致的,我将接入的数据存放在Kafka中,然后解析成CSV格式,最后生成文件并加载到数据库,生成数据表。这里我决定使用Flume来完成这个需求。
实现方法就是通过Java来编写Flume的拦截器,对json进行解析。按照常理的做法肯定是先定义两个实体类,并定义两个Interceptor来解析。但是我觉得肯定有更好的方法来实现这种情况,正好最近抛弃了fastjson的我决定拥抱Gson,去研究如何定义一个实体类和Interceptor来解析。
实体类代码如下:
public class NlkfReqDomain {
private String logday;
@SerializedName(value = "reqcontent", alternate = {"rspcontent"})
private String content;
private String reqdate;
@SerializedName("@version")
private String version;
private String type;
@SerializedName("@timestamp")
private String timestamp;
}
从上面代码可以看出:对于content字段我们使用了注解SerializedName来修饰。
@SerializedName的value属性是序列化和反序列化的字段名称。 alternate是反序列化时没有value对应的字段名的时候的才会用到的备胎名集合
gson版本问题
例如定义两个json格式的字符串
从字符串转换成实体类的过程就是反序列化,从实体类转换成json的过程就是序列化:
不难看出,value属性的inContent值参与了序列化和反序列化,alternate里面的备胎outContent只参与了反序列化。
信心满满的对上面@SerializedName的用法了如指掌的时候,outContent字段解析出来的是null,我以为是忘记了编译,clean之后再次package,发现输出还是null。
因为outContent字段特别长,记得flume中有个event(数据)最大限制,所以我就去查看flume打印的日志,但是没有报错!!!
在本机写了个demo发现outContent是可以正常解析的。难道是代码灵异事件????查找多处资料后,发现
alternate只有在2.4版本之后才能使用
本地使用的Gson2.8,并且将依赖打进了jar包,但是flume中lib下居然有个gson-2.2.2.jar(奔溃中...),根据java的类加载原理,gson2.2加载之后就不会加载gson2.8中重复的class,在删除了gson-2.2.2.jar之后,小手一阵敲打,jps -m | grep xxx | xargs kill -9并sh xxx.sh重启flume,完成解析!!
结语
Python的json解析通过json包就可以,不需要预先定义实体类,是真的方便。以下的代码也可以解决上面的难题,遗憾Flume不支持python实现...。
import json
str1 = "{\"inContent\": \"Hello World\"}"
str2 = "{\"outContent\": \"Hello World\"}"
// 两条命令均输出Hello World
print(json.loads(str1)['inContent'])
print(json.loads(str2)['outContent'])