解析XML和JSON内容的一点技巧
解析XML和JSON内容的一点技巧概述在没有统一标准的情况下,一个系统对接多个外部系统往往会遇到请求接口响应数据异构的情况,有可能返回的是XML,也有可能返回 <root>
<bizKey>16112638767472747178067</bizKey>
<returnMsg>OK</returnMsg>
<returnCode>200</returnCode>
...
</root>
接口2返回内容 <root>
<bid>16112638767472747178068</bid>
<note>成功</note>
<returnStatus>1</returnStatus>
...
</root>
如果在我们系统中为每种格式的内容针对处理显然是不合理的,上面的内容中我们只是关心三种信息,分别是业务ID、状态值和描述信息,那么可不可以抽象这三种信息, 解析XML和JSON根据业务抽象我们需要从XML或者JSON内容中获得三种信息,我们这里将会使用XPath和JSONPath的方式来解析。比如获得接口1的重要信息, {
bid: "/root/bizKey",code: "/root/returnCode",description: "/root/returnMsg"
}
分两步走处理数据内容假设我们从原始的XML和JSON数据中获得了 {
bid: '16112638767472747178067',code: '200',description: 'OK'
}
从接口2获得 {
bid: '16112638767472747178068',code: '1',description: '成功'
}
假设我们从接口1文档获知状态值
因此,我们还必须定义规则把接口1返回的状态值
第一步解析数据获得重要信息以XML为例, public class XmlParseUtils {
private DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
private XPathFactory xpathFactory = XPathFactory.newInstance();
/**
*
* @param param 数据内容
* @param paths 表达式
* @return
* @throws Exception
*/
public Map<String,Object> parse(String param,Map<String,String> paths) throws Exception{
InputSource inputSource = new InputSource(new StringReader(param));
Document document = dbFactory.newDocumentBuilder().parse(inputSource);
Map<String,Object> map = Maps.newHashMap();
for(String key : paths.keySet()) {
XPath xpath = xpathFactory.newXPath();
Node node = (Node) xpath.evaluate(paths.get(key),document,XPathConstants.NODE);
if(node == null) {
throw new Exception("node not found,xpath is " + paths.get(key));
}
map.put(key,node.getTextContent());
}
return map;
}
}
第二步根据规则转换状态值这一步稍稍有点麻烦,不过我们先不考虑代码实现,反正你能想到的可能别人已经帮你实现了。首先我们根据接口文档定义规则,写出规则表达式(或者其他的什么), code.equals("200") ? 2: 3
或者 <#if code == "200"> 2 <#else> 3 <#/if> 亦或者 function handle(arg) {
if(arg == 200) {
return 2;
}
return 3;
}
handle(${code})
以上根据同一份文档定义了三种不同类型的状态值转换规则,肯定需要三种不同的实现。下面一一说明, 三目表达式
public Object evaluateByJexl(String expression,Object> context) {
JexlEngine jexl = new JexlBuilder().create();
JexlExpression e = jexl.createExpression(expression);
JexlContext jc = new MapContext(context);
return e.evaluate(jc);
}
FreeMarker模板<#if code == "200"> 2 <#else> 3 <#/if> 处理这段模板我们可以这么做 /**
*
* @param param FreeMarker模板
* @param context
* @return
* @throws Exception
*/
public String render(String param,Object> context) throws Exception {
Configuration cfg = new Configuration();
StringTemplateLoader stringLoader = new StringTemplateLoader();
stringLoader.putTemplate("myTemplate",param);
cfg.setTemplateLoader(stringLoader);
Template template = cfg.getTemplate("myTemplate","utf-8");
StringWriter writer = new StringWriter();
template.process(context,writer);
return writer.toString();
}
如果 JavaScript代码段function handle(arg) {
if(arg == 200) {
return 2;
}
return 3;
}
handle(${code})
这段 public Object evaluate(String expression) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");
return engine.eval(expression);
}
不同转换规则实现的比较
看起来 或许我们会这样的挑战,在做状态值转换时需要知道当前系统某个业务状态值的情况, <# assign lastCode = GetLastCode(code)> <#if lastCode == "2"> 2 <#elseif code == "200"> 2 <#else> 3 <#/if> 这里我们可以使用Freemarker的特性,自定义Java函数或工具类,在模板中调用。 代码地址https://github.com/Honwhy/xml... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
