Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用java将csv读取为嵌套json_Java_Json_Csv_Jackson_Nested - Fatal编程技术网

如何使用java将csv读取为嵌套json

如何使用java将csv读取为嵌套json,java,json,csv,jackson,nested,Java,Json,Csv,Jackson,Nested,我有这种类型的csv: metric,value,date temp_a,622.0,1477895624866 temp_a,-3.0,1477916224866 temp_a,365.0,1477917224866 temp_b,861.0,1477895624866 temp_b,767.0,1477917224866 我想用javajackson把它转换成json,但不是任何json;它必须是这样的: [ { "metric":"temp_a", "datapoin

我有这种类型的csv:

metric,value,date
temp_a,622.0,1477895624866
temp_a,-3.0,1477916224866
temp_a,365.0,1477917224866
temp_b,861.0,1477895624866
temp_b,767.0,1477917224866
我想用javajackson把它转换成json,但不是任何json;它必须是这样的:

[
  {
    "metric":"temp_a",
    "datapoints":[
      [622, 1477895624866],
      [-3, 1477916224866],
      [365, 1477917224866]
    ]
  },
  {
    "metric":"temp_b",
    "datapoints":[
      [861, 1477895624866],
      [767, 1477917224866]
    ]
  }
]
其中dataponits是一个数组,包含csv中的值和日期

我成功地使用了jackson来获得以下结果:

{metric=temp_a, value=622.0, date=1477895624866}
{metric=temp_a, value=-3.0, date=1477916224866}
{metric=temp_a, value=365.0, date=1477917224866}
{metric=temp_b, value=861.0, date=1477895624866}
{metric=temp_b, value=767.0, date=1477917224866}
但这不是我想要的,jackson文档对我来说有点难以理解和使用,可能POJO或注释可以做到这一点,但我无法理解它们,我找不到如何进行嵌套json

如果我能做得更好,还有别的事,那么杰克逊请告诉我。
谢谢您的帮助。

您不必总是将
CSV
反序列化为
POJO
结构并实现自定义序列化程序。在这种情况下,您还可以:

  • CSV
    反序列化为
    Map
  • 映射中的元素分组到表单
    度量->[[…],[…]]
  • 将上面的
    Map
    转换为另一种形式的
    Map
  • 序列化
    Map
    JSON
示例代码如下所示:

import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;

import java.io.File;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class CsvApp {

    public static void main(String[] args) throws Exception {
        File csvFile = new File("./resource/test.csv").getAbsoluteFile();

        CsvMapper csvMapper = CsvMapper.builder().build();
        MappingIterator<Map> rows = csvMapper
                .readerWithSchemaFor(Map.class)
                .with(CsvSchema.emptySchema().withHeader())
                .readValues(csvFile);

        DataConverter converter = new DataConverter();
        List<Map<String, Object>> result = converter.toMetricDataPoints(rows);

        ObjectMapper jsonMapper = JsonMapper.builder()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .build();

        jsonMapper.writeValue(System.out, result);
    }

}

class DataConverter {

    public List<Map<String, Object>> toMetricDataPoints(MappingIterator<Map> rows) {
        return toStream(rows)
            //group by metric -> [value, date]
            .collect(Collectors.groupingBy(map -> map.get("metric"),
                Collectors.mapping(map -> Arrays.asList(toNumber(map.get("value")), toNumber(map.get("date"))),
                    Collectors.toList())))
            .entrySet().stream()
            // convert to Map: metric + datapoints
            .map(entry -> {
                Map<String, Object> res = new LinkedHashMap<>(4);
                res.put("metric", entry.getKey());
                res.put("datapoints", entry.getValue());

                return res;
            }).collect(Collectors.toList());
    }

    private Stream<Map> toStream(MappingIterator<Map> rowIterator) {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(rowIterator, Spliterator.ORDERED), false);
    }

    private long toNumber(Object value) {
        return new BigDecimal(Objects.toString(value, "0")).longValue();
    }
}
如您所见,我们只使用了基本的
Jackson
功能,其余的操作都是使用
java8
API
实现的

另见:


  • 非常感谢您的帮助,这正是我所寻找的:)但我想知道这是否适用于大型csv文件?这是处理大型csv文件的最佳方式吗?@feiz,这取决于你所说的
    大型文件
    是什么意思。若文件小于数兆字节,则上述代码应该可以工作。上面的代码将所有数据加载到内存中,并在内存中执行操作。所以,在您没有收到
    OutOfMemoryError
    之前,您可以使用上述测试。在其他情况下,您需要了解ok,我明白了,在这种情况下,我认为这段代码会很好地工作,非常感谢:)
    [ {
      "metric" : "temp_a",
      "datapoints" : [ [ 622, 1477895624866 ], [ -3, 1477916224866 ], [ 365, 1477917224866 ] ]
    }, {
      "metric" : "temp_b",
      "datapoints" : [ [ 861, 1477895624866 ], [ 767, 1477917224866 ] ]
    } ]