我一直在尝试将对象序列化为CSV,String但是该对象包含List,@JsonUnwrapped并且不能在List对象上使用。
String
List
@JsonUnwrapped
预期样本输出 :
color,part.name\n red,gearbox\n red,door\n red,bumper
实际输出 :
com.fasterxml.jackson.core.JsonGenerationException: Unrecognized column 'name':
这是我的代码 :(其中大多数是2个POJO)
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import java.io.IOException; import static java.util.Arrays.asList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; public class NestedWrapping { @JsonRootName("Car") @JsonInclude(JsonInclude.Include.NON_DEFAULT) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE) @JsonPropertyOrder({"color"}) public static class Car { @JsonProperty("color") private String color; @JsonFormat(shape = JsonFormat.Shape.STRING) @JacksonXmlElementWrapper(useWrapping = false) private List<Part> parts; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public List<Part> getParts() { return parts; } public void setParts(List<Part> parts) { this.parts = parts; } } @JsonInclude(JsonInclude.Include.NON_DEFAULT) @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE) @JsonPropertyOrder({ "name" }) public static class Part { @JsonProperty("name") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public static void main(String args[]) { try { Car car = new Car(); car.setColor("red"); Part part1 = new Part(); part1.setName("geabox"); Part part2 = new Part(); part2.setName("door"); Part part3 = new Part(); part3.setName("bumper"); car.setParts(asList(part1, part2, part3)); System.out.println("serialized: " + serialize(car, Car.class, true)); } catch (IOException ex) { Logger.getLogger(NestedWrapping.class.getName()).log(Level.SEVERE, null, ex); } } public static final synchronized String serialize(final Object object, final Class type, final Boolean withHeaders) throws IOException { CsvMapper csvMapper = new CsvMapper(); CsvSchema csvSchema; if (withHeaders) { csvSchema = csvMapper.schemaFor(type).withHeader(); } else { csvSchema = csvMapper.schemaFor(type).withoutHeader(); } return csvMapper.writer(csvSchema).writeValueAsString(object); } }
我尝试的一切似乎都没有任何效果,但找不到有效的解决方案。
抱歉,我无缘无故留下的毫无意义的注释,如果您回答了代码,请随时删除它们。
从错误中,我想相信这与您的模式有关Car,该模式的列{"color"}取自@JsonPropertyOrderon Car而不是"name"值。
Car
{"color"}
@JsonPropertyOrder
"name"
您可能想在其中添加"parts",但是会得到与"name"该模式无关的相同错误。
"parts"
在对您的代码进行一些更改之后,我得以序列化和反序列化一个Car对象。
部分
在这里,经过一些其他更改,它需要一个具有单个String值的构造函数,因此添加
@JsonPropertyOrder({"name"}) public static class Part { @JsonProperty("name") private String name; public Part() { this(""); } public Part(String partJSON) { // TODO: Unserialize the parameter... it is a serialized Part string... this.name = partJSON; }
汽车
在这里,您将需要实现一种方法,该方法可以将List<Part>手动转换为CSV可读格式。
List<Part>
这样的方法看起来像这样
@JsonGetter("parts") public String getPartString() { String separator = ";"; StringBuilder sb = new StringBuilder(); Iterator<Part> iter = this.parts.iterator(); while (iter.hasNext()) { Part p = iter.next(); sb.append(p.getName()); if (iter.hasNext()) sb.append(separator); } return sb.toString(); }
另外,不要忘了将模式固定在类的顶部
@JsonPropertyOrder({"color", "parts"}) public static class Car { @JsonProperty("color") private String color; @JsonProperty("parts") private List<Part> parts; public Car() { this.parts = new ArrayList<>(); }
连载
您可以更改serialize方法以将类的类型作为通用类型参数,而不是Class像这样的显式类型。
serialize
Class
public static final synchronized <T> String serialize(final T object, final Boolean withHeaders) throws IOException { CsvMapper csvMapper = new CsvMapper(); CsvSchema csvSchema = csvMapper.schemaFor(object.getClass()); if (withHeaders) { csvSchema = csvSchema.withHeader(); } else { csvSchema = csvSchema.withoutHeader(); } return csvMapper.writer(csvSchema).writeValueAsString(object); }
主-作家
现在,如果您序列化Car,应该会看到
color,parts red,gearbox;door;bumper
主要-读者
然后读取该CSV字符串并遍历 Car.getParts()
Car.getParts()
Car car = mapper.readerFor(Car.class).with(csvSchema).readValue(csv); for (Part p : car.getParts()) { System.out.println(p.getName()); } gearbox door bumper