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

如何通过Aspose.Word Java实现JSON驱动的普通域与表格邮件合并?

解决方案:基于JSON完成Aspose.Words普通域+表格区域邮件合并

核心思路

不需要依赖硬编码XML或分两次执行合并,两种可行方案都能基于单一JSON输入完成需求,以下是具体实现:


方案一:直接用JSON处理两类合并(推荐)

利用Aspose.Words原生的JsonDataSource处理表格区域,同时用普通execute()处理单值域,将两次调用封装成统一逻辑,对外部接口透明。

代码实现(Spring Boot环境)

import com.aspose.words.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MailMergeService {
    public byte[] mergeWord(byte[] templateBytes, String jsonInput) throws Exception {
        // 1. 解析JSON数据
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> dataMap = objectMapper.readValue(jsonInput, new TypeReference<>() {});

        // 分离普通域数据和表格区域数据
        Map<String, Object> commonFields = new HashMap<>();
        String tableRegionName = null;
        List<?> tableData = null;

        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            if (entry.getValue() instanceof List) {
                tableRegionName = entry.getKey();
                tableData = (List<?>) entry.getValue();
            } else {
                commonFields.put(entry.getKey(), entry.getValue());
            }
        }

        // 2. 加载Word模板
        Document doc = new Document(new ByteArrayInputStream(templateBytes));

        // 3. 执行普通域合并
        doc.getMailMerge().execute(
                commonFields.keySet().toArray(new String[0]),
                commonFields.values().toArray()
        );

        // 4. 执行表格区域合并
        if (tableRegionName != null && tableData != null) {
            JsonDataSource jsonDataSource = new JsonDataSource(
                    new ByteArrayInputStream(jsonInput.getBytes(StandardCharsets.UTF_8))
            );
            doc.getMailMerge().executeWithRegions(jsonDataSource);
        }

        // 5. 输出合并后的文档
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        doc.save(outputStream, SaveFormat.DOCX);
        return outputStream.toByteArray();
    }
}

注意事项

  • Word模板中:普通域用{MERGEFIELD title}格式,表格区域需标记{TableStart:Table1}和{TableEnd:Table1}(与JSON中的数组键名一致)
  • Aspose.Words版本需≥19.10(原生支持JsonDataSource)

方案二:JSON转符合要求的XML统一合并

通过Jackson将JSON转换成Aspose.Words可识别的XML结构,一次性调用executeWithRegions()完成两类合并。

步骤1:定义映射实体类

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.List;

@JacksonXmlRootElement(localName = "Root")
public class MergeData {
    @JacksonXmlProperty(localName = "title")
    private String title;

    @JacksonXmlProperty(localName = "header")
    private String header;

    @JacksonXmlElementWrapper(localName = "Table1")
    @JacksonXmlProperty(localName = "Item")
    private List<TableItem> table1;

    // getter、setter省略
}

class TableItem {
    @JacksonXmlProperty(localName = "name")
    private String name;

    @JacksonXmlProperty(localName = "age")
    private Integer age;

    // getter、setter省略
}

步骤2:JSON转XML并执行合并

import com.aspose.words.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;

public class MailMergeXmlService {
    public byte[] mergeWord(byte[] templateBytes, String jsonInput) throws Exception {
        // 1. JSON转XML
        ObjectMapper objectMapper = new ObjectMapper();
        MergeData mergeData = objectMapper.readValue(jsonInput, MergeData.class);

        XmlMapper xmlMapper = new XmlMapper();
        String xmlData = xmlMapper.writeValueAsString(mergeData);

        // 2. 加载XML数据源
        XmlMailMergeDataSource dataSource = new XmlMailMergeDataSource(
                new ByteArrayInputStream(xmlData.getBytes(StandardCharsets.UTF_8)),
                "Root"
        );

        // 3. 执行合并
        Document doc = new Document(new ByteArrayInputStream(templateBytes));
        doc.getMailMerge().executeWithRegions(dataSource);

        // 4. 输出结果
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        doc.save(outputStream, SaveFormat.DOCX);
        return outputStream.toByteArray();
    }
}

关键说明

  • 生成的XML结构符合Aspose要求:根节点为<Root>,普通域作为根节点子元素,表格区域用<Table1>包裹<Item>子节点(对应Word中的区域标记)
  • 此方案适合需要统一用executeWithRegions()处理的场景,但多了一次JSON转XML的开销

最优方案选择

  • 优先选方案一:无需额外转换,逻辑简单,性能更优,仅需两次合并调用但可封装成统一接口,对外部无感知
  • 方案二适合必须用单一executeWithRegions()调用的场景,需确保XML结构与Word模板标记完全匹配

内容的提问来源于stack exchange,提问作者Pankaj Patil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:46:00