You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

关键逻辑说明

  1. JSON与XML互转:通过json-to-xml()将输入JSON转换为XSLT可处理的XML结构,处理完成后用xml-to-json()转回JSON,indent: true()保证输出格式化。
  2. 分组聚合:使用xsl:for-each-group按Category 1、Date 1、Date 2的组合值分组,通过sum()函数对每组的Paid和OS求和。
  3. 字段顺序控制:在输出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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:06:04