尝试使用jackson-data-format-csv解析csv文件,转换成Java对象,最终作为response body 以Json格式返回给用户,遇到几点问题:
第一:解析后字段顺序不对:
要解析csv文件,首先要定义以什么格式解析,即schema。
jackson csv library document 讲的很清楚,在这里定义schema有三种方式:
- 基于一个Java类创建schema
// Schema from POJO (usually has @JsonPropertyOrder annotation) CsvSchema schema = mapper.schemaFor(Pojo.class);
- 在需要schema的时候通过手动添加每个列的方式build构建schema
// Manually-built schema: one with type, others default to "STRING" CsvSchema schema = CsvSchema.builder() .addColumn("firstName") .addColumn("lastName") .addColumn("age", CsvSchema.ColumnType.NUMBER) .build();
- 使用csv文件的第一行列名作为schema,(但这种方式就没办法定义每个字段的类型,只有个名字而已)
// Read schema from the first line; start with bootstrap instance // to enable reading of schema from the first line // NOTE: reads schema and uses it for binding CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader(); ObjectMapper mapper = new CsvMapper(); mapper.readerFor(Pojo.class).with(bootstrapSchema).readValue(json);
public CsvMapper(CsvFactory f)
{
super(f);
// As per #11: default to alphabetic ordering
enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
_untypedSchemas = new LRUMap<JavaType,CsvSchema>(8,32);
_typedSchemas = new LRUMap<JavaType,CsvSchema>(8,32);
}
/**
* Feature that defines default property serialization order used
* for POJO fields (note: does <b>not</b> apply to {@link java.util.Map}
* serialization!):
* if enabled, default ordering is alphabetic (similar to
* how {@link com.fasterxml.jackson.annotation.JsonPropertyOrder#alphabetic()}
* works); if disabled, order is unspecified (based on what JDK gives
* us, which may be declaration order, but is not guaranteed).
*<p>
* Note that this is just the default behavior, and can be overridden by
* explicit overrides in classes (for example with
* {@link com.fasterxml.jackson.annotation.JsonPropertyOrder} annotation)
*<p>
* Feature is disabled by default.
*/
SORT_PROPERTIES_ALPHABETICALLY(false),
因此,如果不强调解析顺序,默认情况下可能会根据创建schema的类内字段的alpha-beta顺序对应csv的列序;
@JsonPropertyOrder({"id","name","description"})
通过这种方式可以定义解析时的列顺序。
有些帖子的例子上还有
CsvMapper mapper = new CsvMapper();
mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
的用法,根据document,其实给配置主要针对如何解析csv文件上的一行元素。
默认情况下会将csv的每一行解析成一个map对象,即一组key-value键值对序列;
但如果利用上面的配置enable了wrap_as_array,则csv的每一行都会被解析为一个array,就一行上的每个column元素都是array中的一个,也即不区分column之间的不同key值。
其实jackson csv还提供了很多配置属性;更多信息还是要查看源码或官方文档。
第二:作为JSON输出时无限循环。
这个问题主要出现于在定义schema的类中同时提供了读取csv文件返回该类为元素的list的解析结果的方法;
解析的结果就变成了例如:
{
"StandardCodeList" : [
"id":"xxxx",
"name":"yyyy",
"description":"this is an example",
"StandardCodeList":[
....,
"StandardCodeList":[
....
]
]
]
}
这样的死循环。将getList的方法从schema定义类中剥离出来就解决这个问题了。
更多应用实例详见:
https://www.programcreek.com/java-api-examples/index.php?api=com.fasterxml.jackson.dataformat.csv.CsvMapper
http://blog.youkuaiyun.com/doctor_who2004/article/details/50760622