猿问

Jackson CSV 映射器不适用于自定义架构

我有这个代码:


CsvSchema sema = CsvSchema.builder()

    .addColumn("name")

    .addColumn("year", CsvSchema.ColumnType.NUMBER)

    .build().withHeader();


ObjectReader reader = new CsvMapper().readerFor(JsonNode.class).with(sema);


JsonNode o = reader.readValue(new FileInputStream(new File("/path/to/test.csv")));

System.out.println(o);

并且test.csv是:


test, year

1,    1

该代码应解析CSV为JSON下一种格式:


{"name":"1","year":1}

但我的输出是:


{"name":"1","year":"1"}

问题是:Jackson将年份解析为String,但我在CSV Schema那一年配置的是Number. 有人知道是什么问题吗?


杰克逊版本是2.9.8,我也试过了2.7.1


至尊宝的传说
浏览 92回答 2
2回答

白猪掌柜的

经过数小时的工作,我为您找到了解决方案。我使用 FlexJson 来配置你的 json 的序列化。&nbsp; &nbsp; <!-- https://mvnrepository.com/artifact/net.sf.flexjson/flexjson --><dependency>&nbsp; &nbsp; <groupId>net.sf.flexjson</groupId>&nbsp; &nbsp; <artifactId>flexjson</artifactId>&nbsp; &nbsp; <version>2.0</version></dependency>它不是很漂亮,但它有效。我希望这对您有所帮助,我相信您可以改进此代码public String generateJsonFromCSV(File csvFile, File schemaJson) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {&nbsp; &nbsp; //Get CsvSchema as Map&nbsp; &nbsp; Map<String, CsvSchema.ColumnType> map = getSchemaMapFromJson(schemaJson);&nbsp; &nbsp; //Create CsvSchema from CsvSchemaMap&nbsp; &nbsp; CsvSchema.Builder schemaBuilder = new CsvSchema.Builder();&nbsp; &nbsp; map.forEach(schemaBuilder::addColumn);&nbsp; &nbsp; CsvSchema schema = schemaBuilder.build();&nbsp; &nbsp; //read CSV&nbsp; &nbsp; CsvMapper csvMapper = new CsvMapper();&nbsp; &nbsp; MappingIterator<Map<?, ?>> mappingIterator = csvMapper.readerFor(Map.class).with(schema).readValues(csvFile);&nbsp; &nbsp; //Get configured JsonSerializer from CsvSchemaMap&nbsp; &nbsp; JSONSerializer jsonSerializer = getJsonSerializer(map);&nbsp; &nbsp; List<Map<?, ?>> lines = mappingIterator.readAll();&nbsp; &nbsp; //remove first line&nbsp; &nbsp; lines.remove(0);&nbsp; &nbsp; //serialize&nbsp; &nbsp; return jsonSerializer.deepSerialize(lines);}/**&nbsp;*&nbsp;* @param schemaMap mapping field to ColumnType&nbsp;* @return a configured JSONSerializer&nbsp;*/private JSONSerializer getJsonSerializer(Map<String, CsvSchema.ColumnType> schemaMap){&nbsp; &nbsp; Map<CsvSchema.ColumnType, Transformer> transformerMap = new EnumMap<>(CsvSchema.ColumnType.class);&nbsp; &nbsp; transformerMap.put(CsvSchema.ColumnType.STRING, new StringTransformer());&nbsp; &nbsp; transformerMap.put(CsvSchema.ColumnType.NUMBER, new NumberTransformer());&nbsp; &nbsp; JSONSerializer jsonSerializer = new JSONSerializer();&nbsp; &nbsp; for (Map.Entry<String, CsvSchema.ColumnType> columnTypeEntry : schemaMap.entrySet()) {&nbsp; &nbsp; &nbsp; &nbsp; jsonSerializer.transform(transformerMap.get(columnTypeEntry.getValue()),columnTypeEntry.getKey());&nbsp; &nbsp; }&nbsp; &nbsp; return jsonSerializer;}/**&nbsp;/**&nbsp;*&nbsp;* @param file JSON CsvSchema&nbsp;* @return fieldname ColumnType mapping&nbsp;* @throws ClassNotFoundException&nbsp;*/private Map<String, CsvSchema.ColumnType> getSchemaMapFromJson(File file) throws ClassNotFoundException {&nbsp; &nbsp; Map<String, String> schema = new JSONDeserializer<Map<String,String>>().deserialize(getResourceFileAsString(file.getName()));&nbsp; &nbsp; Map<String, CsvSchema.ColumnType> result = new HashMap<>(schema.size());&nbsp; &nbsp; for (Map.Entry<String, String> columnSchema : schema.entrySet()) {&nbsp; &nbsp; &nbsp; &nbsp; result.put(columnSchema.getKey(), CsvSchema.ColumnType.valueOf(columnSchema.getValue().toUpperCase()));&nbsp; &nbsp; }&nbsp; &nbsp; return result;}输出将是[{"name":"foobar","year":1986},{"name":"testtest","year":777}]

天涯尽头无女友

强制CsvMapper使用给定类型的最好方法是使用POJO. 在这种情况下CsvMapper,知道类型并在可能的情况下自动转换它。让我们创建一个示例数据:name,year1,12,23,2(在您的示例中,第一列名称是,test但我认为这只是一个错误,应该是name。)下面的应用程序显示了如何解析CSV和编写JSON使用POJO:import com.fasterxml.jackson.annotation.JsonCreator;import com.fasterxml.jackson.annotation.JsonProperty;import com.fasterxml.jackson.databind.MappingIterator;import com.fasterxml.jackson.databind.ObjectMapper;import com.fasterxml.jackson.databind.ObjectReader;import com.fasterxml.jackson.databind.SerializationFeature;import com.fasterxml.jackson.dataformat.csv.CsvMapper;import com.fasterxml.jackson.dataformat.csv.CsvSchema;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;public class CsvApp {&nbsp; &nbsp; public static void main(String[] args) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; File csvFile = new File("./resource/test.csv").getAbsoluteFile();&nbsp; &nbsp; &nbsp; &nbsp; CsvMapper csvMapper = new CsvMapper();&nbsp; &nbsp; &nbsp; &nbsp; CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader();&nbsp; &nbsp; &nbsp; &nbsp; ObjectReader reader = csvMapper.readerFor(User.class).with(bootstrapSchema);&nbsp; &nbsp; &nbsp; &nbsp; MappingIterator<User> iterator = reader.readValues(csvFile);&nbsp; &nbsp; &nbsp; &nbsp; List<User> users = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; iterator.forEachRemaining(users::add);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Users read from CSV file:");&nbsp; &nbsp; &nbsp; &nbsp; users.forEach(System.out::println);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println();&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Users in JSON format:");&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper jsonMapper = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; jsonMapper.enable(SerializationFeature.INDENT_OUTPUT);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(jsonMapper.writeValueAsString(users));&nbsp; &nbsp; }}class User {&nbsp; &nbsp; private final String name;&nbsp; &nbsp; private final int year;&nbsp; &nbsp; @JsonCreator&nbsp; &nbsp; public User(@JsonProperty("name") String name, @JsonProperty("year") int year) {&nbsp; &nbsp; &nbsp; &nbsp; this.name = name;&nbsp; &nbsp; &nbsp; &nbsp; this.year = year;&nbsp; &nbsp; }&nbsp; &nbsp; public String getName() {&nbsp; &nbsp; &nbsp; &nbsp; return name;&nbsp; &nbsp; }&nbsp; &nbsp; public int getYear() {&nbsp; &nbsp; &nbsp; &nbsp; return year;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String toString() {&nbsp; &nbsp; &nbsp; &nbsp; return "User{" +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "name='" + name + '\'' +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ", year=" + year +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '}';&nbsp; &nbsp; }}上面的代码打印:Users read from CSV file:User{name='1', year=1}User{name='2', year=2}User{name='3', year=2}Users in JSON format:[ {&nbsp; "name" : "1",&nbsp; "year" : 1}, {&nbsp; "name" : "2",&nbsp; "year" : 2}, {&nbsp; "name" : "3",&nbsp; "year" : 2} ]
随时随地看视频慕课网APP

相关分类

Java
我要回答