使用Jackson和Immutables从某些CSV列创建Map

uurity8g  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(183)

我有一个CSV,我通过Jackson解析它,为每一行创建一个不可变类型的列表。CSV有一些列来表示一个集合,如:

Name,Age,Height,Item1,Item2,Item3,Item4,Item5
AB,1,1.123,ABC,DEF,GHI,JKL,MNO

目前我将其解析为以下类型:

@Value.Immutable
@JsonSerialize
@JsonDeserialize
@JsonPropertyOrder({"name","age","height","item1","item2","item3","item4","item5"})

public abstract class Schema {

    abstract String name();
    abstract int age();
    abstract double height();

    abstract String item1();
    abstract String item2();
    abstract String item3();
    abstract String item4();
    abstract String item5();

}

我使用的是来自不可变类的csv模式:

CsvMapper csvMapper = new CsvMapper()
                .enable(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS)
                .enable(CsvParser.Feature.EMPTY_STRING_AS_NULL);
        CsvSchema schema = csvMapper.typedSchemaFor(Schema.class).withHeader();

这很好用,但是我想把这些项目做成一个Map,或者使用它们的列名或者项目号作为键。

abstract Map<String, String> items();
//or
    abstract Map<int, String> items();

我可以通过创建第二个对象来创建集合,但我想知道是否有一种方法可以让Jackson/Immutables自动完成此操作?不幸的是,我无法更改CSV文件,因为它来自外部源。

**编辑:**作为一个稍微笨拙的解决方案,我可以使用以下方法创建Map:

@Value.Redacted abstract String item1();
    @Value.Redacted abstract String item2();
    @Value.Redacted abstract String item3();
    @Value.Redacted abstract String item4();
    @Value.Redacted abstract String item5();

    @Value.Derived
    public Map<Integer, String> items() {
        Map<Integer, String> items = new HashMap<>();
        items.put(1, item1());
        items.put(2, item2());
        items.put(3, item3());
        items.put(4, item4());
        items.put(5, item5());
        return items;
    }

这样隐藏了个别物品,但不知是否有更有效的方法?

ipakzgxi

ipakzgxi1#

您可以使用MappingIterator将csv反序列化为Map<String, String>。如果您使用csv:

Name,Age,Height,Item1,Item2,Item3,Item4,Item5
AB,1,1.123,ABC,DEF,GHI,JKL,MNO

您可以定义一个CsvSchema模式,该模式使用第一行作为标题,并从CsvMapperMap器示例化一个新的MappingIterator迭代器:

CsvMapper mapper = new CsvMapper();
// use first row as header
CsvSchema schema = CsvSchema.emptySchema().withHeader();
MappingIterator<Map<String, String>> it = mapper.readerFor(Map.class)
        .with(schema)
        .readValues(csv);

因此,您可以读取数据行并将其转换为Map<String, String>Map,删除不需要的列:

CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.emptySchema().withHeader();
MappingIterator<Map<String, String>> it = mapper.readerFor(Map.class)
        .with(schema)
        .readValues(csv);

Map<String, String> items = it.next();
items.remove("Name");
items.remove("Age");
items.remove("Height");
//ok, it prints {Item1=ABC, Item2=DEF, Item3=GHI, Item4=JKL, Item5=MNO}
System.out.println(items);

相关问题