web-dev-qa-db-ja.com

Java)でCsvMapperを使用してヘッダーをcsvファイルに動的に割り当てる方法

誰か助けてもらえますか? csvファイルを読み取ってPOJOにシリアル化するのに行き詰まっています。 jacksonライブラリのCsvMapperを使用しています。読み取りとシリアル化の部分が完了し、問題なく動作します。問題は、ユーザーがヘッダー/列を移動して、CSVファイルの値もアルファベット順であるとシリアル化でアルファベット順に仮定する場合です。
例(以下のファイルの最初の行にはヘッダーがあり、2番目の行には個人の詳細値があります)_personNameHeader,personAgeHeader Wiliam,32_

今私のPOJOは次のとおりです

_@JsonIgnoreProperties(ignoreUnknown = true)
// @JsonPropertyOrder(value = {"personNameHeader", "personAgeHeader" })
public class PersonDetailsCSVTemplate  {

@JsonProperty("personNameHeader")
private String name;

@JsonProperty("personAgeHeader")
private String age;

//Public constructor and getters and setters...
_

これは、CSVから値を読み取り、クラスにマップするためのコードです。

_import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
...

    CsvMapper csvMapper = new CsvMapper();    
    CsvSchema schema = csvMapper.typedSchemaFor(PersonDetailsCSVTemplate.class).withHeader();
          MappingIterator<PersonDetailsCSVTemplate  > dataIterator = csvMapper.readerFor(PersonDetailsCSVTemplate.class).with(schema)
            .readValues(data);

     while (dataIterator.hasNextValue()) {
        PersonDetailsCSVTemplate dataCSV = dataIterator.nextValue();
}
_

シリアル化後、CsvMapperが以下をマップしたことがわかります:_PersonDetailsCSVTemplate.name = "32"_および_PersonDetailsCSVTemplate.age = "Wiliam"_

クラスに@JsonPropertyOrder(value = {"personNameHeader", "personAgeHeader" })アノテーションを付けると、CSVは常に名前列の後に年齢列が続きますが、これは理想的ではありません。

誰かがうまくいくと思うことを提案できますか?よろしく

6
Wil Ferraciolli

sortedBy を使用して、csvデータでプロパティが出現する順序を指定できます。

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonPropertyOrder(value = { "personNameHeader", "personAgeHeader" })
static class PersonDetailsCSVTemplate
{
    @JsonProperty("personNameHeader")
    private String name;

    @JsonProperty("personAgeHeader")
    private String age;

    public String getName()
    {
        return name;
    }

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

    public String getAge()
    {
        return age;
    }

    public void setAge(String age)
    {
        this.age = age;
    }

    @Override
    public String toString()
    {
        return "PersonDetailsCSVTemplate [name=" + name + ", age=" + age + "]";
    }
}

@JsonPropertyOrderを保持または残すことができますが、出力には影響しません。

@Test
public void sort() throws IOException
{
    CsvMapper csvMapper = new CsvMapper();
    CsvSchema schema = csvMapper
        .typedSchemaFor(PersonDetailsCSVTemplate.class)
        .withHeader()
        .sortedBy("personNameHeader", "personAgeHeader")
        .withColumnSeparator(',')
        .withComments();

    MappingIterator<PersonDetailsCSVTemplate> dataIterator =
        csvMapper
            .readerFor(PersonDetailsCSVTemplate.class)
            .with(schema)
            .readValues("personNameHeader,personAgeHeader\r\n"
                +
                "Wiliam,32\r\n");

    while (dataIterator.hasNextValue())
    {
        PersonDetailsCSVTemplate dataCSV = dataIterator.nextValue();

        System.out.println(dataCSV);
    }
}

出力:

PersonDetailsCSVTemplate [name=Wiliam, age=32]
4
A4L

Jackson 2.7以降、withColumnReordering(true)の代わりにsortedBy()を使用できます。

CsvSchema schema = csvMapper
    .typedSchemaFor(PersonDetailsCSVTemplate.class)
    .withHeader()
    .withColumnReordering(true);
4
Nathan