Java中使用XSLT实现JSON对象转换遇到问题求助
使用XSLT 3.0在Java中实现嵌套JSON的分组聚合转换
需求分析
需要将包含嵌套数组的JSON对象转换,核心逻辑是对orderProps数组按Category 1、Date 1、Date 2进行分组,对每组的Paid和OS字段求和,保留其他字段并输出指定格式的JSON。
完整XSLT样式表
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all"> <!-- 设置输出为XML,后续转为JSON --> <xsl:output method="xml" indent="yes" encoding="UTF-8"/> <!-- 主模板:处理输入的JSON转XML后的根节点 --> <xsl:template match="/"> <xsl:variable name="json-xml" select="json-to-xml(.)"/> <xsl:apply-templates select="$json-xml/*"/> </xsl:template> <!-- 处理order对象 --> <xsl:template match="*[@key='order']"> <map key="order"> <!-- 复制orderid字段 --> <xsl:apply-templates select="*[@key='orderid']"/> <!-- 处理orderProps数组 --> <array key="orderProps"> <!-- 按Category 1、Date 1、Date 2分组 --> <xsl:for-each-group select="*[@key='orderProps']/*" group-by="concat(*[@key='Category 1'], '|', *[@key='Date 1'], '|', *[@key='Date 2'])"> <map> <!-- 输出分组后的字段,按指定顺序排列 --> <string key="Date 2" select="current-group()/*[@key='Date 2']/text()"/> <number key="OS" select="sum(current-group()/*[@key='OS']/xs:decimal(text()))"/> <number key="Paid" select="sum(current-group()/*[@key='Paid']/xs:decimal(text()))"/> <string key="Category 1" select="current-group()/*[@key='Category 1']/text()"/> <string key="Date 1" select="current-group()/*[@key='Date 1']/text()"/> </map> </xsl:for-each-group> </array> </map> <!-- 将处理后的XML转为格式化JSON --> <xsl:value-of select="xml-to-json(., map { 'indent' : true() })"/> </xsl:template> <!-- 通用模板:复制简单字段(如orderid) --> <xsl:template match="*[@key='orderid']"> <number key="orderid" select="text()"/> </xsl:template> </xsl:stylesheet>
关键逻辑说明
- JSON与XML互转:通过
json-to-xml()将输入JSON转换为XSLT可处理的XML结构,处理完成后用xml-to-json()转回JSON,indent: true()保证输出格式化。 - 分组聚合:使用
xsl:for-each-group按Category 1、Date 1、Date 2的组合值分组,通过sum()函数对每组的Paid和OS求和。 - 字段顺序控制:在输出map时按需求指定字段顺序,确保最终JSON的字段排列符合预期。
Java调用代码(使用Saxon-HE)
XSLT 3.0需要支持的处理器,推荐使用Saxon-HE(Maven坐标:net.sf.saxon:Saxon-HE:12.4),以下是Java中执行转换的示例:
import net.sf.saxon.s9api.*; import java.io.File; import java.io.FileWriter; import java.io.IOException; public class JsonXsltTransformer { public static void main(String[] args) throws SaxonApiException, IOException { // 初始化Saxon处理器 Processor processor = new Processor(false); XsltCompiler compiler = processor.newXsltCompiler(); // 加载XSLT样式表 XsltExecutable executable = compiler.compile(new File("transform.xsl")); XsltTransformer transformer = executable.load(); // 设置输入JSON File inputJson = new File("input.json"); XdmNode input = processor.newDocumentBuilder().build(inputJson); transformer.setInitialContextNode(input); // 设置输出文件 File outputJson = new File("output.json"); Serializer serializer = processor.newSerializer(new FileWriter(outputJson)); serializer.setOutputProperty(Serializer.Property.METHOD, "json"); serializer.setOutputProperty(Serializer.Property.INDENT, "yes"); transformer.setDestination(serializer); // 执行转换 transformer.transform(); } }
注意事项
- 确保使用支持XSLT 3.0的处理器,如Saxon 9.8及以上版本。
- 若JSON字段名包含特殊字符,XSLT中通过
@key属性匹配时需严格对应。
内容的提问来源于stack exchange,提问作者Yadav_Jogi
相关产品推荐
相关产品推荐

