Gson:备胎alternate的版本问题

681 阅读2分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

前言

最近在数据接入的工作中,接入了两种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'])