简体   繁体   English

数组的 Jackson-CSV 模式

[英]Jackson-CSV schema for array

I have CSV file which I need to parse.我有需要解析的CSV文件。 The schema for this file is following:此文件的架构如下:

name, contacts - where contacts are many strings for each person where the number of this contact columns is not regular.姓名,联系人 - 其中联系人是每个人的许多字符串,其中此联系人列的数量不规则。

For example:例如:

john, john@wick.com, 123 123 123, fb/john.wick
mike, 123 0303 11
dave,

I'm trying to create a CsvSchema with Jacskon CSV for my bean:我正在尝试为我的 bean 创建一个带有Jacskon CSVCsvSchema

public class Person {
    private String name;
    private String[] contacts;
}

By creating custom schema:通过创建自定义架构:

CsvSchema schema = CsvSchema.builder()
    .addColumn("name")
    .addArrayColumn("contacts", ",")
    .build(); 

But I am getting this:但我得到了这个:

com.fasterxml.jackson.dataformat.csv.CsvMappingException: Too many entries: expected at most 2

How to with Jackson CSV solve problem like that?如何使用Jackson CSV解决这样的问题?

Java code: Java代码:

CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.builder()
    .addColumn("name")
    .addArrayColumn("contacts", ",")
    .build();
MappingIterator<Person> it = mapper.readerFor(Person.class).with(schema)
    .readValues(csvString);
List<Person> all = it.readAll();

You can use CsvParser.Feature.WRAP_AS_ARRAY feature and read whole row as List<String> .您可以使用CsvParser.Feature.WRAP_AS_ARRAY功能并将整行读取为List<String> In constructor you can convert List to Person object.在构造函数中,您可以将List转换为Person对象。 See below example:见下面的例子:

import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvParser;

import java.io.File;
import java.util.List;
import java.util.stream.Collectors;

public class CsvApp {

    public static void main(String[] args) throws Exception {
        File csvFile = new File("./resource/test.csv").getAbsoluteFile();

        CsvMapper csvMapper = new CsvMapper();
        csvMapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);

        MappingIterator<List<String>> rows = csvMapper.readerFor(List.class).readValues(csvFile);
        List<Person> persons = rows.readAll().stream()
                .filter(row -> !row.isEmpty())
                .map(Person::new)
                .collect(Collectors.toList());

        persons.forEach(System.out::println);
    }
}

class Person {

    private String name;
    private List<String> contacts;

    public Person(List<String> row) {
        this.name = row.remove(0);
        this.contacts = row;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<String> getContacts() {
        return contacts;
    }

    public void setContacts(List<String> contacts) {
        this.contacts = contacts;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", contacts=" + contacts +
                '}';
    }
}

For your input above code prints:对于您输入的上述代码打印:

Person{name='john', contacts=[john@wick.com, 123 123 123, fb/john.wick]}
Person{name='mike', contacts=[123 0303 11]}
Person{name='dave', contacts=[]}

I think the problem is with the column separator being the same as the array column separator.我认为问题在于列分隔符与数组列分隔符相同。

You can use ;你可以使用; instead of , in your CSV.而不是,在您的 CSV 中。

Should be: john,john@wick.com;123 123 123;fb/john.wick应该是: john,john@wick.com;123 123 123;fb/john.wick

This way you can continue to use the features of Jackson instead of having to manually instantiate from a List of Strings.这样您就可以继续使用 Jackson 的功能,而不必从字符串列表中手动实例化。

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

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