jackson-dataformats-text
jackson-dataformats-text copied to clipboard
CSV generator does not support Object values for properties (nested Objects)
I have written a short test class to identify a problem I am encountering when attempting to convert a POJO to a JSON String.
NOTE that in my Java code I tried to configure the CsvMapper v2.18.3 to ignore certain types of problems but the Exception is still thrown.
Dependency:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.18.3</version>
</dependency>
The Java code is:
package ca.cdr.admin.web.controller;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvParser;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
public class JacksonCsvSerializationTest {
@JsonIgnoreProperties(ignoreUnknown=true)
private static class Name {
private String firstName;
private String lastName;
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@JsonProperty("name")
public String getName() {
return this.firstName + " " + this.lastName;
}
}
@JsonIgnoreProperties(ignoreUnknown=true)
private static class Person {
@JsonProperty("id")
private int id = 1;
@JsonProperty("names")
private Collection<Name> names = new HashSet<Name>();
public Person(Name name) {
this.names.add(name);
}
}
public static void main(String args[]) throws IOException {
Name name = new Name("first", "last");
Person person = new Person(name);
CsvSchema.Builder csvBuilder = new CsvSchema.Builder();
CsvMapper csvMapper = (CsvMapper) new CsvMapper()
.configure(CsvParser.Feature.FAIL_ON_MISSING_COLUMNS, false)
.configure(CsvParser.Feature.FAIL_ON_MISSING_HEADER_COLUMNS, false)
.configure(JsonParser.Feature.IGNORE_UNDEFINED, true)
.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true);
csvBuilder.addColumn(new CsvSchema.Column(1, "id"));
csvBuilder.addColumn(new CsvSchema.Column(2, "names"));
CsvSchema csvSchema = csvBuilder.build().withStrictHeaders(false);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
csvMapper.writer(csvSchema).writeValue(baos, person);
System.out.println("-->" + baos.toString() + "<--");
}
}
The ERROR I get is:
Exception in thread "main" com.fasterxml.jackson.dataformat.csv.CsvWriteException: CSV generator does not support Object values for properties (nested Objects) (through reference chain: ca.cdr.admin.web.controller.JacksonCsvSerializationTest$Person["names"]->java.util.HashSet[0])
at com.fasterxml.jackson.dataformat.csv.CsvWriteException.from(CsvWriteException.java:25)
at com.fasterxml.jackson.dataformat.csv.CsvGenerator._reportMappingError(CsvGenerator.java:1108)
at com.fasterxml.jackson.dataformat.csv.CsvGenerator.writeStartObject(CsvGenerator.java:648)
at com.fasterxml.jackson.core.base.GeneratorBase.writeStartObject(GeneratorBase.java:328)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:179)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107)
at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:732)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:183)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:502)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:341)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1574)
at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1275)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1098)
at ca.cdr.admin.web.controller.JacksonCsvSerializationTest.main(JacksonCsvSerializationTest.java:62)
Any assistance would be appreciated!
Well, what do you want your CSV to look like? Both the list and the object are not straight-forward to map.
Quick note: usually it's a Bad Idea to use this for any tests:
@JsonIgnoreProperties(ignoreUnknown=true)
since it tends to mask all kinds of problems.
Aside from that, yeah, nested POJOs are not supported. List/arrays with simple Scalar types (Numbers, Strings, Booleans) are. As per exception:
"CSV generator does not support Object values for properties (nested Objects) "
this is current limitation and someone would need to work on adding support -- probably first specifying what kind of convention would be used. For List/arrays/Collections, support is in a way that the whole value is encoded within a single cell. For POJOs this approach would be more difficult.
Thanks for the quick response!
Maybe this code I provided can be used to test that future feature.
Let me know if you want to add it somewhere as a @Disabled Test.
Thanks again,
Kevin