定制 Jackson 解析器来完成对复杂格式 XML 的解析
先点赞再看,养成好习惯背景 前阵子,公司渠道平台对接了一个新渠道,使用 XML 格式的报文交互。虽然 XML 格式有点复杂且“古老”,但好在它功能强大,支持属性、注释,比 JSON 要加的更直观和清晰。
但是吧,功能强大的同时也有一些弊端。某些复杂的 XML 并不能像 JSON 那样直接和实体类映射,因为 XML 是支持属性(attribute)的,如果一个标签同时拥有多个属性,或者属性和值,就不太好实体类映射了,比如下面这种报文:
解决方案 像上面这种复杂一点的报文,也是有解决方案的,只是有点不太优雅。比如我可以创建一个 ExtendInfo 类,定义 key/value 两个属性,然后再将 extendInfos 定义为一个 List,也可以完成解析:
public class Root {
private List extendInfos;
// getter and setters....
}
可是这个数据格式很明显是个键值对格式,弄个 List 来存储,是不是有点太傻了?要是能用 Map 来接收 extendInfos 的数据该多好……
Jackson 是个功能非常强大的序列化库,除了支持 JSON 以外,还支持很多其他格式,比如 XML。而且 Jackson 还可以自定义对解析器的增强,通过对
JsonDeserializer
接口的扩展,可以完成更复杂数据的解析:
基于 Jackson,可以定制化一下解析器,来完成上面复杂数据的解析,将 extendInfos 解析为一个 Map,方便程序的处理先定义一个 AttrMap ,用来标记我们这个特殊的数据类型,直接继承 HashMap 就好:
public class AttrMap extends HashMap {
}
接着将 Root 中的类型修改为这个 AttrMap:
public class Root {
private AttrMap extendInfos;
// getter and setters....
}
【定制 Jackson 解析器来完成对复杂格式 XML 的解析】然后是自定义的类型解析器 - AttrMapDeserializer,在这个解析器里将报文和 AttrMap 映射
public class AttrMapDeserializer extends JsonDeserializer> {
@Override
public AttrMap deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken curToken ;
AttrMap attrMap = new AttrMap<>();
while ((curToken = p.nextToken()) !=null && curToken.id() == JsonTokenId.ID_FIELD_NAME){
//skip start token
p.nextToken();
String key = null,value = https://www.it610.com/article/null;
while ((curToken = p.nextToken()) != null
&&
curToken.id()== JsonTokenId.ID_FIELD_NAME){
String attrName = p.getCurrentName();
String attrValue = p.nextTextValue();
if("key".equals(attrName)){
key = attrValue;
}
//处理和123213两种形式
if("value".equals(attrName) || "".equals(attrName)){
value = https://www.it610.com/article/attrValue;
}
}
attrMap.put(key,value);
}
return attrMap;
}
}
好了,大功告成,来测试一下:
String body = " \n" +
" \n" +
"\n" +
"\n" +
"\n" +
" \n" +
" \n" +
" ";
JacksonXmlModule module = new JacksonXmlModule();
module.addDeserializer(AttrMap.class, new AttrMapDeserializer());
ObjectMapper objectMapper = new XmlMapper(module);
Root root = objectMapper.readValue(body, Root.class);
System.out.println(root);
//output
Root{extras={birthday=19870101, address=北京, gender=M, userName=周关}}
附录 Jackson XML 模块
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
2.12.2
Jackson XML Wiki
https://github.com/FasterXML/...
原创不易,禁止未授权的转载。如果我的文章对您有帮助,就请点赞/收藏/关注鼓励支持一下吧??????
推荐阅读
- 定制一套英文学习方案
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- Android系统启动之init.rc文件解析过程
- 小程序有哪些低成本获客手段——案例解析
- Spring源码解析_属性赋值
- Android下的IO库-Okio源码解析(一)|Android下的IO库-Okio源码解析(一) 入门
- 08_JVM学习笔记_类命名空间解析
- WebSocket|WebSocket 语法解析