简体   繁体   English

使用 Apache Camel 从另一个 API 使用 JSON 并将其写入 CSV

[英]Consume JSON from another API using Apache Camel and write it in CSV

I am new in apache camel.我是 apache 骆驼的新手。 I would like to consume json data from another api's end point url (http://localhost:8080/employeePayload).我想从另一个 api 的端点 url (http://localhost:8080/employeePayload) 使用 json 数据。 I would like to consume this json data, unmarshal it to a POJO using apache camel and write it to CSV file.我想使用此 json 数据,使用 apache camel 将其解组到 POJO 并将其写入 CSV 文件。 Before I write it in CSV I need to add delimiter |" for each property/column. Also I have to add header and trailer records to the CSV file. Header consists of some static column names and some run time names. Header column count will not be same as the json data. Header has 15 column and json has 110 columns).在我用 CSV 编写它之前,我需要为每个属性/列添加分隔符 |"。此外,我必须将标题和尾部记录添加到 CSV 文件中。标题由一些静态列名称和一些运行时名称组成。标题列数将与 json 数据不同。Header 有 15 列,json 有 110 列)。

is there a way to bind the json/pojo to CSV file without using setter method(as I have 110 properties, can't use setter for all)?有没有办法在不使用 setter 方法的情况下将 json/pojo 绑定到 CSV 文件(因为我有 110 个属性,不能全部使用 setter)?

Can someone suggest what would be the best way to achieve this?有人可以建议什么是实现这一目标的最佳方法吗?

If headers part is not clear, please tell me how to write the json to CSV with delimiter(|").如果标题部分不清楚,请告诉我如何使用分隔符 (|") 将 json 写入 CSV。

Edit: I am able to consume json from another API.编辑:我可以从另一个 API 使用 json。 However I am not sure how to write it in CSV with delimiter using apache camel or any other lib without using getters and setters.但是,我不确定如何在不使用 getter 和 setter 的情况下使用 apache camel 或任何其他 lib 使用分隔符在 CSV 中编写它。

I found the answer.我找到了答案。 As the development progressed I had many questions which which I have posted them in stackoverflow.随着开发的进行,我有很多问题,我已将它们发布在 stackoverflow 中。

I decided to sum up everything I found.我决定总结我发现的一切。

Please refer the below post.请参考以下帖子。 Unable to add header and footer to the file using Apache Camel Bindy 无法使用 Apache Camel Bindy 向文件添加页眉和页脚

This solution had fixed many issues that I had in various stage.这个解决方案解决了我在不同阶段遇到的许多问题。

Issue 1) Added dynamic header and footer to the flat file using BindyFixedLengthDataFormat.问题 1) 使用 BindyFixedLengthDataFormat 向平面文件添加动态页眉和页脚。 As the name suggests it's fixed length.顾名思义,它是固定长度的。 I had to assign maximum length and trim the whitespaces after generating the body.我必须在生成主体后分配最大长度并修剪空格。 (I still may need consider using different class as I do not want the length to be fixed). (我仍然可能需要考虑使用不同的类,因为我不希望长度固定)。 BindyCsvDataFormat does not have the option to add dynamic headers and footer to the file. BindyCsvDataFormat 没有向文件添加动态页眉和页脚的选项。

Issue 2) I had the requirement to replace the pipe delimiter with |".问题 2) 我需要用 |" 替换管道分隔符。

Issue 3) Instead of using jetty to expose the end point url which will be hard coded I have used rest configuration so that hostname will no longer be hard coded and you can deploy to any environment.问题 3)我没有使用 jetty 来公开硬编码的端点 url,而是使用了 rest 配置,这样主机名将不再是硬编码,您可以部署到任何环境。

@Component
    public class EmployeePackageRoute extends RouteBuilder {
    
        @Autowired
        private Header header;
        
        private Trailer footer;
        
        private String file_name;
        
        @SuppressWarnings("deprecation")
        @Override
        public final void configure() {
            
            System.out.println("fetching employee details from employee api");
            
            final SimpleDateFormat TARGET_DATE_FORMAT = new SimpleDateFormat("YYYYMMDDHHMMSS");
            String date = TARGET_DATE_FORMAT.format(new Date());
            
            String year = date.substring(0, 8);
            String hr = date.substring(9, 13);
    
            try {
                restConfiguration().component("jetty").port(8000).bindingMode(RestBindingMode.json);
                rest("/api/test/getTestResponse")
                .get().consumes(MediaType.APPLICATION_JSON_VALUE).route().setBody().constant("return test response");
                
                rest("/api/bcr/recurringPaymentsDeduct")
                .post().consumes(MediaType.APPLICATION_JSON_VALUE).type(RecurringPaymentResults.class).outType(ResponseEntity.class).route()
                .process(
                        ex -> {
                            
                            RecurringPaymentResults result = ex.getIn().getBody(RecurringPaymentResults.class);
                            List<RecurringPaymentsDeduct> employee = result.getResults();
                            file_name = Constants.FILE_NUMBER_DEV+"_"+date+"_"+Constants.AUMBCR_HRMD+result.getSequenceNumber()+"_"+Constants.DUT8G2I+".SAP";
                            header.setHeader7(Constants.FILE_NUMBER_DEV+"_"+date+"_"+Constants.AUMBCR_HRMD+result.getSequenceNumber()+"_"+Constants.DUT8G2I+".SAP");
                            
                            header.setHeader8(year);
                            header.setHeader9(hr);
                            header.setHeader10(Constants.ENVIRONMENT);
                            
                            footer = new Footer("Footer",(employee.size()+2));
                            
                            ex.getOut().setBody(employee);
                        })
                .to("seda:recurringPaymentsFeed");
                
                final DataFormat recurringPaymentsBindy = new BindyFixedLengthDataFormat(RecurringPaymentsDeduct.class);
                
                from("seda:recurringPaymentsFeed")
                .startupOrder(2)
                .log("add footer to the file")
                .process(
                        ex -> {
                            
                            Map<String, Object> headerObjMap = new HashMap<String,Object>();
                            headerObjMap.put(Header.class.getName(), header);
                            System.out.println(" *** file_name 1 - "+file_name);
                            Map<String, Object> footerObjMap = new HashMap<String,Object>();
                            footerObjMap.put(Footer.class.getName(), footer);
                            
                            ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, headerObjMap);
                            ex.getOut().setBody(ex.getIn().getBody());
                            ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER, footerObjMap);
                            
                        })
                .marshal(recurringPaymentsBindy)
                .convertBodyTo(byte[].class, "iso-8859-1")
                .setBody(body().regexReplaceAll("\\|", "\\|\""))
                .log("csv processed")
                .to("file://app/bcr-files?fileName=recurringPaymentsDeduct.SAP")
                .end();
                
                
            } catch(Exception e) {
                System.out.println("Error occurred while processing employee data: "+e.getMessage());
                e.printStackTrace();
            }
        }
        
    }

@Data
@Section(number = 2)
@FixedLengthRecord(header = Header.class, footer = Trailer.class)
public class RecurringPaymentsDeduct implements Serializable {

    private static final long serialVersionUID = 1L;
    
    @DataField(pos = 1, length = 10, delimiter = "|", trim = true)
    public String RECTY;
    
    @DataField(pos = 2, length = 10, delimiter = "|", trim = true)
    public String CLIID;
    
    @DataField(pos = 3, length = 10, delimiter = "|", trim = true)
    public String INTCA;
    
    @DataField(pos = 4, length = 10, delimiter = "|", trim = true)
    public String ORDNO;
    
    @DataField(pos = 5, length = 10, delimiter = "|", trim = true)
    public String IOPER;
    
    @DataField(pos = 6, length = 10, delimiter = "|", trim = true)
    public String INFTY;
    
    @DataField(pos = 7, length = 10, delimiter = "|", trim = true)
    public String SUBTY;
    
    @DataField(pos = 8, length = 10, delimiter = "|", trim = true)
    public String BEGDA;
    
    @DataField(pos = 9, length = 10, delimiter = "|", trim = true)
    public String ENDDA;
    
    @DataField(pos = 10, length = 10, trim = true)
    public String OBJPS;
        
}

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("adp")
@Data
@Section(number = 1)
@FixedLengthRecord()
public class Header implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 5, delimiter = "|", trim = true)
    private String header1;
    
    @DataField(pos = 2, length = 5, delimiter = "|", trim = true)
    private String header2;
    
    @DataField(pos = 3, length = 15, delimiter = "|", trim = true)
    private String header3;
    
    @DataField(pos = 4, length = 60, delimiter = "|", trim = true)
    private String header4;
    
    @DataField(pos = 5, length = 15, delimiter = "|", trim = true)
    private String header5;
    
    @DataField(pos = 6, length = 30, delimiter = "|", trim = true)
    private String header6;
    
    @DataField(pos = 7, length = 30, delimiter = "|", trim = true)
    private String header7;
    
    @DataField(pos = 8, length =  8, pattern = "YYYYMMDD", delimiter = "|", trim = true)
    private String header8;
    
    @DataField(pos = 9, length = 6, delimiter = "|", trim = true)
    private String header9;
    
    @DataField(pos = 10, length = 1, delimiter = "|", trim = true)
    private String header10;
    
    @DataField(pos = 11, length = 2, delimiter = "|", trim = true)
    private String header11;
    
    @DataField(pos = 12, length = 10, delimiter = "|", trim = true)
    private String header12;
    
    @DataField(pos = 13, length = 10, delimiter = "|", trim = true)
    private String header13;
    
    @DataField(pos = 14, length = 10, align = "L", trim = true)
    private String header14;
}

@Data
@Section(number = 3)
@FixedLengthRecord()
public class Footer implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 7, delimiter = "|", trim = true)
    private String trailer;
    
    @DataField(pos = 2, length = 5, align = "L", trim = true)
    private int count;
    
    public Footer() {
        
    }
    
    public Footer(String trailer, int count) {
        this.trailer = trailer;
        this.count = count;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM