2016-09-16 70 views
0

我有一个CSV文件看起来像这样:如何将表转换为地图的地图

request.car.model (STRING),request.car.make (STRING),request.person.lastname (STRING),other.person.birthdate (DATE),other.person.length (INTEGER) 
BMW,7 series,Doe,31/12/1980,170 
Tesla,Model S,Smith,1/1/1975,172 
Volvo,C40,Johnson,13/11/1982,189 

第一行头,与被括号之间解析类型。标题使用点符号,非常像Javascript会解析一个复杂的对象。

我需要做的是为CSV文件中的每一行创建一个Java Map<String, Serializable>。例如,第一行需要导致map在Java中看起来像这样:

Map<String, Serializable> requestCarMap = new HashMap<>(); 
requestCarMap.put("make", "BMW"); 
requestCarMap.put("model", "7 series"); 
Map<String, Serializable> requestPersonMap = new HashMap<>(); 
requestPersonMap.put("lastName", "Doe"); 
Map<String, Serializable> requestMap = new HashMap<>(); 
requestMap.put("car", (HashMap) requestCarMap); 
requestMap.put("pesron", (HashMap) requestPersonMap); 
Map<String, Serializable> otherPersonMap = new HashMap<>(); 
otherPersonMap.put("birthdate", new Date(1980,12,31)); 
Map<String, Serializable> otherMap = new HashMap<>(); 
otherMap.put("person", (HashMap) otherPersonMap); 
Map<String, Serializable> map = new HashMap<>(); 
map.put("request", (HashMap) requestMap); 
map.put("other", (HashMap) otherMap); 

我目前有创建一个基于价值观的地图,但是,如果没有分裂头,并把它在子图的方法:

protected static Map<String, Serializable> parseRecord(CSVRecord record, CSVRecord header) { 
    final Map<String, Serializable> map = new HashMap<>(); 
    for (int i = 0; i < record.size(); i++) { 
     String headerField = getHeader(header.get(i)); 
     String[] headerFieldPart = headerField.split("\\."); 
     String headerFieldType = getHeaderFieldType(header.get(i)); 
     Object recordField = getRecordField(headerFieldType, record.get(i)); 
     if (recordField != null) { 
      map.put(headerField, (Serializable) recordField); 
     } else { 
      log.warn("Skipped value for record item: " 
        + record.get(i)); 
     } 
    } 
    return map; 
} 

我怎样才能把在子图中的值作为例如在通用的方式?我不知道列的名称或地图的前面嵌套深度。我无法弄清楚在subMap不存在,存在等情况下工作的逻辑。任何智能解决方案?任何能帮助我解决这个问题的库?

回答

2

基本上,在点上分割标题,迭代零件,并根据相关零件切换目标映射指针。

像这样(假设你得到了CSV-物降):

public static void main(String[] args) { 
    String[] headers = { "request.car.model", "request.car.make", "request.buyer" }; 
    String[] values = { "a", "b", "c" }; 

    Map<String, Serializable> outer = new HashMap<>(); 

    for(int i = 0; i < headers.length; i++) { 
     String header = headers[i]; 
     String value = values[i]; 

     String[] parts = header.split("\\."); 
     Map<String, Serializable> targetMap = outer; 
     for(int j = 0; j < parts.length - 1; j++) 
      targetMap = (Map<String, Serializable>) targetMap.computeIfAbsent(parts[j], x -> new HashMap<>()); 
     targetMap.put(parts[parts.length - 1], value); 
    } 

    System.out.println(outer.get("request")); 
} 

注意,如果头是一致的,这只会工作,也就是说,作为“AA值没有这样的事情“之后是”aab“的值。

+0

与所提供的CSV测试,它的工作原理就像一个魅力。非常感谢你! –

0

仅供参考下面是完整的方法:

protected static Map<String, Serializable> parseRecord(CSVRecord record, CSVRecord fullHeader) { 
    if (record == null) { 
     log.warn("Record is null."); 
     return null; 
    } 
    log.info("Parsing record number: " + (record.getRecordNumber() - 1)); 
    log.debug(" with content: " + record.toString()); 
    final Map<String, Serializable> map = new HashMap<>(); 
    for (int i = 0; i < record.size(); i++) { 
     String headerFieldType = getHeaderFieldType(fullHeader.get(i)); 
     Object recordField = getRecordField(headerFieldType, record.get(i)); 
     if (recordField != null) { 
      String headerField = getHeaderField(fullHeader.get(i)); 
      String[] headerFieldPart = headerField.split("\\."); 
      Map<String, Serializable> targetMap = map; 
      for (int j = 0; j < headerFieldPart.length - 1; j++) { 
       targetMap = (Map<String, Serializable>) targetMap.computeIfAbsent(headerFieldPart[j], x -> new HashMap<>()); 
      } 
      targetMap.put(headerFieldPart[headerFieldPart.length - 1], (Serializable) recordField); 
     } else { 
      log.warn("Skipped value for record item: " 
        + record.get(i)); 
     } 
    } 
    log.debug("Parsed map: " + map); 
    return map; 
} 

而生成的日志:

INFO Parsing record number: 1 
DEBUG with content: CSVRecord [comment=null, mapping=null, recordNumber=2, values=[BMW, 7 series, Doe, 31/12/1980, 170]] 
INFO Parsed map: {request={car={model=BMW, make=7 series}, person={lastname=Doe}}, other={person={birthdate=Thu Jan 31 00:12:00 CET 1980, length=170}}} 
INFO Parsing record number: 2 
DEBUG with content: CSVRecord [comment=null, mapping=null, recordNumber=3, values=[Tesla, Model S, Smith, 1/1/1975, 172]] 
INFO Parsed map: {request={car={model=Tesla, make=Model S}, person={lastname=Smith}}, other={person={birthdate=Wed Jan 01 00:01:00 CET 1975, length=172}}} 
INFO Parsing record number: 3 
DEBUG with content: CSVRecord [comment=null, mapping=null, recordNumber=4, values=[Volvo, C40, Johnson, 13/11/1982, 189]] 
INFO Parsed map: {request={car={model=Volvo, make=C40}, person={lastname=Johnson}}, other={person={birthdate=Wed Jan 13 00:11:00 CET 1982, length=189}}}