背景
从kafka
中消费数据后拿到的是protobuf
序列化后的字节数组,转化为Java
中的proto
对象后,需要将这些protocol
对象继续处理成Json
串写入elasticsearch
。
各种问题
Json工具选择
刚开始尝试使用fastJson等工具来执行序列化,结果发现对于protobuf
这种特殊对象,这些序列化工具都会报错,比如fastJson
会提示UnsupportedOperationException: This field is not of enum type
。最后在网上查找资料,发现Google
专门提供了工具类来实现proto
对象的Json
化,com.google.protobuf.util.JsonFormat
。
可以参考这篇论文,https://segmentfault.com/a/1190000020270374
使用例子
JsonFormat.printer()
.includingDefaultValueFields()
.printingEnumsAsInts()
.preservingProtoFieldNames()
.print(element);
这几个选项设置能够控制序列化时的输出结果,是很有用的。
Json转Map工具
转为Json之后,需要将Json转为Map,从而写入ElasticSearch。这里最开始选择了Gson工具
map = new Gson().fromJson(mapJson,Map.class);
然而存入ES之后,发现原来的整形数据被转成了float型,后面都加了小数点。于是,还是换成了FastJson工具,本来因为可能存在安全问题不想用的。
json = JSON.parseObject(mapJson, Map.class);
这次是可以用的,转换结果正确。
long型数据
本来以为都没问题了,结果发现proto中的long型数据在JsonFormat转为json之后,变成了String,这是这个工具类内部默认执行的类型映射,搞了半天,没有什么选项可以自定义映射,而且又不能继承和重写,索性把这个工具类复制了一份,自己把内部映射修改了一下。
后话
要学会举一反三,这个ES格式问题在开发中出了很多次,每次都是发布之后才发现,于是一次一次修改,本来出现一次就应该检查一下其他格式是否也有问题的。