现在很多应用都采用json格式进行数据交换,把业务逻辑通过硬编码实现,导致大量的json解析,如果json数据源很复杂,通过代码解析将是噩梦般的存在。如果数据源格式变动比较大,也很难避免空指针异常。
这个demo工程演示了利用xslt模板解析json源数据,生成新数据的过程。先把json转换成xml数据,通过调用定制xslt模板转换成xml格式的目标数据,再转换成json格式的新数据。程序通过固定框架+xml模板来实现不同的业务需求,虽然增加了一点xml和json格式的相互转换的性能消耗,但是可以有效避免硬编码,保持了代码稳定性,这种性能开销还是可以接受的。当一个业务系统在增加新功能时仅仅通过配置模板就能实现,或者仅需补充少量的编码,那对生产效率的提高还是很有帮助的,特别是在多人合作开发的项目上,不需要做一些因为代码修改产生的动作,比如代码提交,合并,发布等,也能有效避免代码冲突。
原理如下:

动手实践:

工程下载路径:
https://gitcode.net/yeunix_aa/json-demo.git
demo工程本地启动后把测试数据拷入页面,执行转换即可。测试数据在工程的资源路径下

模板常用语法说明:
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' >
<xsl:template match='/'>
<root>
<!--定制输出result新格式数据-->
<result>
<!--输出常量,默认字符串-->
<code>0000</code>
<!--输出整形常量-->
<intCode type='long'>101</intCode>
<!--输出浮点数-->
<doubleVar type='double'>99.85</doubleVar>
<!--输出布尔常量-->
<boolCode type='boolean'>true</boolCode>
<!--根据xpath路径输出,数组下标从1开始-->
<xpathOut><xsl:value-of select='/root/goods[1]/code'/></xpathOut>
<!--条件判断-->
<xsl:if test="/root/goods[1]/products/type='base'">
<comments>满足条件时输出</comments>
<type><xsl:value-of select='/root/goods[1]/products/type'/></type>
</xsl:if>
<!--多条件判断-->
<xsl:choose>
<xsl:when test="/root/goods[1]/products/type='base'">
<multiCheck>base</multiCheck>
</xsl:when>
<xsl:when test="/root/goods[1]/products/type='comp'">
<multiCheck>comp</multiCheck>
</xsl:when>
<xsl:otherwise>
<multiCheck>other</multiCheck>
</xsl:otherwise>
</xsl:choose>
<!--因为xml无法区分对象和对象数组,需要在模板中设置type属性,明确输出json对象还是数组-->
<!--循环使用,输出数组type=array-->
<!--position()用于控制循环次数-->
<xsl:for-each select='/root/goods[1]/products/attrs[position() < 4 ]'>
<attrList type='array'>
<code><xsl:value-of select='code'/></code>
<value><xsl:value-of select='value'/></value>
</attrList>
</xsl:for-each>
<!--循环使用带条件过滤,只输出code是21000前缀并且value值长度小于等于6的记录-->
<!--几个保留字符的转义表达
< ==> <
> ==> >
" ==> "
& ==> &
-->
<xsl:for-each select="/root/goods[1]/products/attrs[starts-with(code,'21000') and string-length(value) <= 6 ]" >
<withCondList type='array'>
<code><xsl:value-of select='code'/></code>
<value><xsl:value-of select='value'/></value>
</withCondList>
</xsl:for-each>
</result>
</root>
</xsl:template>
</xsl:stylesheet>