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

Apache Camel实现空行分隔键值对文本转POJO及CSV方案

解决方案

Bindy的KeyValue模式原生仅支持数字类型tag做键匹配,确实无法直接适配字符串键名的键值对格式,不需要硬适配该组件,以下是可直接落地的实现方式:

方案1:自定义处理器解析(最推荐,零额外依赖、逻辑可控)

第一步:修正原有路由的拆分逻辑

你原有的分隔符\n\r\n存在跨系统兼容问题,先统一换行符后按空行拆分记录,大文件场景开启流式处理避免内存溢出:

from("file://data/input")
    .convertBodyTo(String.class)
    // 统一替换Windows换行符,避免分隔失效
    .setBody(body().replaceAll("\\r", ""))
    // 按空行拆分单条用户记录,开启流式处理
    .split(body().tokenize("\n\n")).streaming()
    .to("direct:card");

第二步:自定义解析逻辑映射POJO

不需要使用KeyValue格式的反序列化,直接在路由中加处理器,按字符串键名匹配字段赋值,之后直接用Bindy的CSV序列化能力输出即可:

from("direct:card")
    .process(exchange -> {
        String singleRecord = exchange.getIn().getBody(String.class);
        User user = new User();
        String[] fieldLines = singleRecord.split("\\n");
        for (String line : fieldLines) {
            line = line.trim();
            if (line.isEmpty()) continue;
            // 按第一个冒号拆分键值,兼容值中包含冒号的场景
            String[] keyValue = line.split("\\s*:\\s*", 2);
            if (keyValue.length < 2) continue;
            String fieldKey = keyValue[0];
            String fieldValue = keyValue[1];
            // 按文本中的实际键名映射到POJO字段
            switch (fieldKey) {
                case "Name": user.setName(fieldValue); break;
                case "City": user.setCity(fieldValue); break;
                case "Country": user.setCountry(fieldValue); break;
                default: // 非目标字段直接忽略
            }
        }
        exchange.getIn().setBody(user);
    })
    // 序列化输出CSV,自动生成表头
    .marshal().bindy(BindyType.Csv, User.class)
    .to("file://data/output?fileName=users.csv");

第三步:调整User类注解适配CSV序列化

去掉原来的KeyValue相关注解,换成CSV序列化对应的注解即可:

@CsvRecord(separator = ",", generateHeaderColumns = true)
public class User {
    @DataField(pos = 1, columnName = "Name")
    String name;
    @DataField(pos = 2, columnName = "City")
    String city;
    @DataField(pos = 3, columnName = "Country")
    String country;

    // 保留原有getter/setter方法即可
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getCity() {return city;}
    public void setCity(String city) {this.city = city;}
    public String getCountry() {return country;}
    public void setCountry(String country) {this.country = country;}
}

方案2:通用键值对解析扩展(适合字段多、不想硬写映射的场景)

如果字段数量多不想手动写switch判断,可以提前做字段名和Setter方法的映射,读取到键名时反射调用对应Setter赋值即可,本质逻辑和方案1一致,只是把硬编码映射改成配置化映射,适合字段经常调整的场景。

注意:不要为了这个场景引入重量级的第三方解析库,自定义几行代码的解析逻辑性能远高于通用格式解析库,调试也更简单。


内容的提问来源于stack exchange,提问作者Daniele Ravizza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:21:18