Writing CSV with Jackson

“How to use jackson-dataformat-csv, part 2”

Now that we know how to read CSV with Jackson…

Simple, “untyped” writing of CSV data

final CsvMapper CSV_MAPPER = new CsvMapper();
final Object[] value = new Object[] { // could use List as well
new Object[] { "foo", 13, true },
new Object[] { "bar", 28, false };
String csv = CSV_MAPPER.writeValueAsString(value);
// foo,13,true
// bar,28,false
try (StringWriter strW = new StringWriter()) {
SequenceWriter seqW = MAPPER.writer()
.writeValues(strW);
seqW.write(new Object[] {"foo", 13, true });
seqW.write(Arrays.asList("bar", 28, false ));
seqW.close();
String csv = strW.toString();
// same as above
}
CsvSchema schema = CsvSchema.emptySchema()
.withQuoteChar('\'') // instead of double-quote
.withColumnSeparator(';') // instead of comma
.withLineSeparator("\r\n") // instead of \n
;
String csv = CSV_MAPPER.writer(schema)
.writeValueAsString(value);
// foo;13;true
// bar;28;false
try (StringWriter strW = new StringWriter()) {
SequenceWriter seqW = CSV_MAPPER.writer()
.writeValues(strW);
seqW.write(Arrays.asList("name", "age", "validated"));
seqW.write(Arrays.asList(bar", 28, false ));
// ... and so on
}

Con POJOs, por favor

// manually create by adding columns in order:
CsvSchema schema = CsvSchema.builder()
.addColumn("name")
.addColumn("age")
.addColumn("validated")
.build();
// or read from POJO
@JsonPropertyOrder({ "name", "age", "validated" }) // important!
// ^^^ without annotation properties ordered alphabetically
public class Person {
public String name;
public int age;
public boolean validated;
public Person(String n, int a, boolean v) {
name = n;
age = a;
validated = v;
}
}
CsvSchema altSchema = CSV_MAPPER.schemaFor(Person.class)
try (StringWriter strW = new StringWriter()) {
// NOTE! Below will introspect and apply schema!
SequenceWriter seqW = MAPPER.writerWithSchemaFor(Person.class)
.writeValues(strW);
seqW.write(new Person("Bob", 37, false))
seqW.write(new Person("Jeff", 28, true))
}
// Bob,37,false
// Jeff,28,true
final CsvSchema schema = CSV_MAPPER.schemaFor(Person.class)
.withHeader();
// and with write sequence from above, we'd get:
//
// name,age,validated
// Bob,37,false
// Jeff,28,true

Special output: Arrays/Lists

@JsonPropertyOrder({ "name", "value", "tags" })
public class Metric {
public String name;
public double value;
public Collection<String> tags;
}
final CsvSchema schema = CSV_MAPPER.schemaFor(Metric.class)
.withHeader();
try (StringWriter strW = new StringWriter()) {
SequenceWriter seqW = MAPPER.writer(schema)
.writeValues(strW);
seqW.write(new Metric("latency", 0.2, Arrays.asList( "http", "rest")));
}
// name,value,tags
// latency,0.2,http;rest

Anything else? Oh yes, configuration

Configuration using CsvSchema

Configuration using CsvGenerator.Feature’s

CsvMapper mapper = CsvMapper.builder()
.enable(CsvGenerator.Feature.ALWAYS_QUOTE_EMPTY_STRINGS)
.build();

And That’s All, Folks!

Open Source developer, most known for Jackson data processor (nee “JSON library”), author of many, many other OSS libraries for Java, from ClassMate to Woodstox