简体   繁体   中英

Selective Serialization to CSV, Java

I am using jsefa library to selectively deserialize a csv for eg. maping only header no. 1,3,5 to my object, this works fine.

Now I want to do the opposite of it selectively serialize my object to header postion 1,3,5 and rest positions should get separated by semicolon (;) automatically. So the output would look something like this:

Header1;Header2;Header3;Header4;Header5;Header6;Header7
bla1;;bla3;;bla5

Can anybody suggest, how can this be done with jsefa or with any other library.

This is certainly achievable with Super CSV. Just supply a null entry in the nameMapping array to always write a blank column.

private static void writePartial() throws IOException {
    Person person1 = new Person("John", "K", "Smith");
    Person person2 = new Person("Sally", "T", "Brown");

    CsvPreference csvPrefs = new CsvPreference.Builder('"', ';', "\n").build();
    String[] nameMapping = new String[] { "firstName", null, "lastName" };

    try (ICsvBeanWriter writer = new CsvBeanWriter(new FileWriter("output.csv"), csvPrefs)) {
        writer.writeHeader("firstName", "middleName", "lastName");
        for( Person p : Arrays.asList(person1, person2) ) {
            writer.write(p, nameMapping);
        }
    }
}

You should get the following output:

firstName;middleName;lastName
John;;Smith
Sally;;Brown

That's probably the easiest solution, but if you're after something more flexible (you might want to validate the field value, but never write it for example), then you can create a custom cell processor to ensure the field is never written. Just define a cell processor that always ignores the value in the bean:

public class Ignore extends CellProcessorAdaptor {

    @Override
    public Object execute(Object value, CsvContext context) {
        return null;
    }

}

And then use it:

private static void writePartial() throws IOException {
    Person person1 = new Person("John", "K", "Smith");
    Person person2 = new Person("Sally", "T", "Brown");

    CsvPreference csvPrefs = new CsvPreference.Builder('"', ';', "\n").build();
    String[] nameMapping = new String[] { "firstName", "middleName", "lastName" };
    CellProcessor[] processors = new CellProcessor[] { new Optional(), new Ignore(), new Optional() };

    try (ICsvBeanWriter writer = new CsvBeanWriter(new FileWriter("output.csv"), csvPrefs)) {
        writer.writeHeader(nameMapping);
        for( Person p : Arrays.asList(person1, person2) ) {
            writer.write(p, nameMapping, processors);
        }
    }
}

So you could chain it together new NotNull(new Ignore()) to validate that the bean's middleName field always has a value, but to never write it. It also means if you change your mind later on and want to write the value, you can replace the Ignore() processor with Optional() (or NotNull() , or whatever you like) and see that it should then write the middle name field, instead of ignoring it.

Just use uniVocity-parsers as it is MUCH simpler and faster than any other CSV parsing library for Java:

To read:

CsvParserSettings settings = new CsvParserSettings();
settings.selectIndexes(1, 3, 5);

CsvParser parser = new CsvParser(settings);
List<String[]> parsedRows = parser.parseAll(yourJavaIoReader);

To write:

CsvWriterSettings settings = new CsvWriterSettings();
settings.selectIndexes(1, 3, 5);

CsvWriter writer = new CsvWriter(outputWriter, settings);
writer.writeAllRowsAndClose(buildMyListOfRowsWith3Elements());

Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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