需要多个columNames映射到单义性的单个场 [英] Need to map multiple columNames to a single field in Univocity

查看:199
本文介绍了需要多个columNames映射到单义性的单个场的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class MyPOJO implements Serializable
{

    private static final long serialVersionUID = 1L;
    @Parsed(field = "UniqueCode")
    private String            code;
    @Parsed(field = "Name")
    private String            name;
    @Parsed(field = "dogId")
    private String            someOtherId;


    //------Getters and Setters-------
    public String getCode()
    {
        return code;
    }
    public void setCode(String code)
    {
        this.code = code;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public String getSomeOtherId()
    {
        return someOtherId;
    }
    public void setSomeOtherId(String someOtherId)
    {
        this.someOtherId = someOtherId;
    }



}

现在我需要映射一个字段,例如someOtherId多个头名(例如:dogId,CATID,cowId等),从不同的CSV文件的即将到来。因此,在文件中假设的 1.csv 称为标题栏 dogId 应该映射到POJO字段 someOtherId 而在文件中的 2.csv 标题 CATID 应该映射到同一领域即 someOtherId 。可能吗?怎么样?

Now I need to map a single field,for example someOtherId with multiple header Names (e.g: "dogId","catId","cowId" etc) coming from different csv files. So suppose in files 1.csv the header column called dogId should map to POJO field someOtherId whereas in file 2.csv the header catId should map to the same field i.e. someOtherId. Is it possible? How?

推荐答案

您可以轻松地如果与值列 someOtherId 总是在相同的位置解析这个,不无论哪个文件正在使用。

You can parse this easily if the columns with values for someOtherId are always in the same location, no matter which files you are using.

class MyPOJO implements Serializable
{

    private static final long serialVersionUID = 1L;
    @Parsed(field = "UniqueCode")
    private String            code;
    @Parsed(field = "Name")
    private String            name;
    @Parsed(index = 2) //anything goes here, "catId", "cowId", etc
    private String            someOtherId;

    ...
}

如果列位置每个输入文件不同,你可以实现你自己的行处理器。我创建了下面的实现,可能会为你工作。它本质上可能标题映射到一个索引。这些指标应与在你的类注释索引。

If the column position varies in each input file, you could implement your own row processor. I created the following implementation that will probably work for you. It essentially maps possible headers to an index. These indexes should match with the indexes annotated in your class.

我会打破细节下来帮助你了解我所做的。

I'll break the details down to help you understand what I did.

    @Parsed(index = 0)
    private String code;
    @Parsed(index = 1)
    private String name;
    @Parsed(index = 2) //cowId, dogId or catId or anything else
    private String someOtherId;

创建围绕现有BeanProcessor实现一个包装

public class MyBeanProcessor<T> extends AbstractRowProcessor{
    //here's the wrapped bean processor.
    private final BeanListProcessor<T> processor;

    //we need a LinkedHashMap here to keep the the correct ordering.
    private final LinkedHashMap<String, Integer> headersToCapture;

    public MyBeanProcessor(Class<T> beanType, LinkedHashMap<String, Integer> headersToCapture){
        processor = new BeanListProcessor<T>(beanType);
        this.headersToCapture = headersToCapture;
    }

    // work with parsed headers to find out what is in the input
    @Override
    public void rowProcessed(String[] inputRow, ParsingContext context) {
        //... more details later
    }

    @Override
    public void processEnded(ParsingContext context) {
        processor.processEnded(context);
    }

    public List<T> getBeans(){
        return processor.getBeans();
    }
}

这个自定义行处理器的预期用法:

//keys are possible headers, and values are the indexes where each header will be mapped to:
Map<String, Integer> headerPositions = new LinkedHashMap<String, Integer>();
headerPositions.put("UniqueCode", 0);
headerPositions.put("Name", 1);
headerPositions.put("dogId", 2);
headerPositions.put("catId", 2);
headerPositions.put("cowId", 2);

CsvParserSettings settings = new CsvParserSettings();
//we want headers
settings.setHeaderExtractionEnabled(true);

//let's use the custom row processor:
MyBeanProcessor<MyPOJO> processor = new MyBeanProcessor<MyPOJO>(MyPOJO.class, headerPositions);
settings.setRowProcessor(processor);

CsvParser parser = new CsvParser(settings);
parser.parse(<YOUR_INPUT_HERE>);

List<MyPOJO> myPojos = processor.getBeans();

rowProcessed 方法的实现:

Implementation of the rowProcessed method:

    private int[] headerIndexes = null;
    private String[] row = null;

    @Override
    public void rowProcessed(String[] inputRow, ParsingContext context) {
        if(headerIndexes == null){ //initializes the indexes to capture
            processor.processStarted(context);
            String[] parsedHeaders = context.headers();

            LinkedHashSet<Integer> indexes = new LinkedHashSet<Integer>();
            for(String headerToCapture : headersToCapture.keySet()){
                int headerIndex = ArgumentUtils.indexOf(parsedHeaders, headerToCapture);
                if(headerIndex != -1){
                    indexes.add(headerIndex);
                }
            }
            headerIndexes = ArgumentUtils.toIntArray(indexes);
            row = new String[indexes.size()]; //creates a reusable row with the number of columns captured
        }

        //once the input format is known, we can collect the values from the expected positions:
        for(int i = 0; i < headerIndexes.length; i++){
            int indexToCapture = headerIndexes[i];
            if(indexToCapture < inputRow.length){
                row[i] = inputRow[indexToCapture];
            } else {
                row[i] = null;
            }
        }
        //and submit a row with the values in the correct places to the actual bean processor
        processor.rowProcessed(row, context);
    }

我在本地测试这一点,并预期以下输入被解析,无论身在何处的头文件位于:

I tested this locally and the following inputs are parsed as expected, no matter where the headers are located:

UniqueCode,T,name,dogId
1,99,2,3

生成

MyPOJO{code='1', name='2', someOtherId='3'}

输入2

cowId,Z,UniqueCode,T,name
4,99,5,99,6

生成

MyPOJO{code='5', name='6', someOtherId='4'}

希望这有助于。

这篇关于需要多个columNames映射到单义性的单个场的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆