Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.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
使用Spring MVC和jackson dataformat CSV自动包含CSV标题_Csv_Spring Mvc_Jackson - Fatal编程技术网

使用Spring MVC和jackson dataformat CSV自动包含CSV标题

使用Spring MVC和jackson dataformat CSV自动包含CSV标题,csv,spring-mvc,jackson,Csv,Spring Mvc,Jackson,我正在努力使jackson dataformat csv包含csv标题 现在我可以输出实体集合(列表),但标题不存在,这使得文件无法解析,因为列没有标题 我的MVC配置(缩短): @Configuration @EnableWebMvc public class MvcConfig extends WebMvcConfigurerAdapter { @Autowired private Environment env; public static final Stri

我正在努力使jackson dataformat csv包含csv标题

现在我可以输出实体集合(列表),但标题不存在,这使得文件无法解析,因为列没有标题

我的MVC配置(缩短):

@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private Environment env;

    public static final String JSON_OBJECT_MAPPER_NAME = "json";
    public static final String CSV_OBJECT_MAPPER_NAME = "csv";

    private static final TimeZone OUTPUT_DATE_TIMEZONE = TimeZone.getTimeZone(ZoneOffset.UTC);
    private static final DateFormat OUTPUT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

    @Autowired
    @Qualifier(value = JSON_OBJECT_MAPPER_NAME)
    private ObjectMapper jsonObjectMapper;

    @Autowired
    @Qualifier(value = CSV_OBJECT_MAPPER_NAME)
    private ObjectMapper csvObjectMapper;

    public MvcConfig() {
        super();
    }



    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(true);
        configurer.ignoreAcceptHeader(false);
        configurer.defaultContentType(MediaType.APPLICATION_JSON);
        configurer.useJaf(false);

        final Map<String,MediaType> mediaTypes = new HashMap<>();
        mediaTypes.put("html", MediaType.TEXT_HTML);
        mediaTypes.put("json", MediaType.APPLICATION_JSON);
        mediaTypes.put("csv", new MediaType("text","csv", Charset.forName("utf-8")));
        configurer.mediaTypes(mediaTypes);
    }




    @Bean(name = JSON_OBJECT_MAPPER_NAME)
    @Primary
    public ObjectMapper jsonObjectMapper(){
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.indentOutput(Boolean.parseBoolean(env.getProperty("jsonPrettyPrint")));
        builder.timeZone(OUTPUT_DATE_TIMEZONE);
        builder.dateFormat(OUTPUT_DATE_FORMAT);
        return builder.build();
    }

    @Bean(name = CSV_OBJECT_MAPPER_NAME)
    public ObjectMapper csvObjectMapper(){
        CsvMapper csvMapper = new CsvMapper();

        //csvMapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);

        csvMapper.setTimeZone(OUTPUT_DATE_TIMEZONE);
        csvMapper.setDateFormat(OUTPUT_DATE_FORMAT);

        csvMapper.registerModule(new CsvMappingModule());
        csvMapper.registerModule(new JodaModule());

        return csvMapper;
    }



    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(createJsonHttpMessageConverter());
        converters.add(createCsvHttpMessageConverter());
    }

    private HttpMessageConverter<Object> createJsonHttpMessageConverter() {
        return createHttpMessageConverter(jsonObjectMapper, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8);
    }

    private HttpMessageConverter<Object> createCsvHttpMessageConverter() {
        return createHttpMessageConverter(csvObjectMapper, TEXT_CSV);
    }

    private HttpMessageConverter<Object> createHttpMessageConverter(ObjectMapper objectMapper, MediaType... supportedMediaTypes){
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
        converter.setSupportedMediaTypes(Lists.newArrayList(supportedMediaTypes));
        return converter;
    }
}
@Controller
@RequestMapping("/api/history")
public class HistoricController {


    @Autowired
    public IHistoryService historyService;
    @Autowired
    public IThingService thingService;

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    public List<HistoryDTO> findHistory(@PathVariable("id") Long thingId){
        Thing thing = thingService.find(thingId);
        return historyService.findByThing(thing);
    }

}
[
    {
      "location": {
        "id": 101483,
        "name": "City A"
      },
      "dateEnteredLocation": "2016-06-06T18:44:03.000Z",
      "dateLeavingLocation": "2016-06-13T13:02:34.000Z"
    },
    {
      "location": {
        "id": 101483,
        "name": "City A"
      },
      "dateEnteredLocation": "2016-06-13T16:02:34.000Z",
      "dateLeavingLocation": "2016-06-15T11:54:57.000Z"
    },
    {
      "location": {
        "id": 101485,
        "name": "City C"
      },
      "dateEnteredLocation": "2016-06-16T04:05:06.000Z",
      "dateLeavingLocation": "2016-06-16T11:34:58.000Z"
    }
]
2016-06-06T18:44:03.000Z,2016-06-13T13:02:34.000Z,101483,City A
2016-06-13T16:02:34.000Z,2016-06-15T11:54:57.000ZZ,101483,City A
2016-06-16T04:05:06.000Z,2016-06-16T11:34:58.000Z,101485,City C
但当我尝试使用CSV格式时,我得到:

@Configuration
@EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private Environment env;

    public static final String JSON_OBJECT_MAPPER_NAME = "json";
    public static final String CSV_OBJECT_MAPPER_NAME = "csv";

    private static final TimeZone OUTPUT_DATE_TIMEZONE = TimeZone.getTimeZone(ZoneOffset.UTC);
    private static final DateFormat OUTPUT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

    @Autowired
    @Qualifier(value = JSON_OBJECT_MAPPER_NAME)
    private ObjectMapper jsonObjectMapper;

    @Autowired
    @Qualifier(value = CSV_OBJECT_MAPPER_NAME)
    private ObjectMapper csvObjectMapper;

    public MvcConfig() {
        super();
    }



    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(true);
        configurer.ignoreAcceptHeader(false);
        configurer.defaultContentType(MediaType.APPLICATION_JSON);
        configurer.useJaf(false);

        final Map<String,MediaType> mediaTypes = new HashMap<>();
        mediaTypes.put("html", MediaType.TEXT_HTML);
        mediaTypes.put("json", MediaType.APPLICATION_JSON);
        mediaTypes.put("csv", new MediaType("text","csv", Charset.forName("utf-8")));
        configurer.mediaTypes(mediaTypes);
    }




    @Bean(name = JSON_OBJECT_MAPPER_NAME)
    @Primary
    public ObjectMapper jsonObjectMapper(){
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.indentOutput(Boolean.parseBoolean(env.getProperty("jsonPrettyPrint")));
        builder.timeZone(OUTPUT_DATE_TIMEZONE);
        builder.dateFormat(OUTPUT_DATE_FORMAT);
        return builder.build();
    }

    @Bean(name = CSV_OBJECT_MAPPER_NAME)
    public ObjectMapper csvObjectMapper(){
        CsvMapper csvMapper = new CsvMapper();

        //csvMapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);

        csvMapper.setTimeZone(OUTPUT_DATE_TIMEZONE);
        csvMapper.setDateFormat(OUTPUT_DATE_FORMAT);

        csvMapper.registerModule(new CsvMappingModule());
        csvMapper.registerModule(new JodaModule());

        return csvMapper;
    }



    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(createJsonHttpMessageConverter());
        converters.add(createCsvHttpMessageConverter());
    }

    private HttpMessageConverter<Object> createJsonHttpMessageConverter() {
        return createHttpMessageConverter(jsonObjectMapper, MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8);
    }

    private HttpMessageConverter<Object> createCsvHttpMessageConverter() {
        return createHttpMessageConverter(csvObjectMapper, TEXT_CSV);
    }

    private HttpMessageConverter<Object> createHttpMessageConverter(ObjectMapper objectMapper, MediaType... supportedMediaTypes){
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);
        converter.setSupportedMediaTypes(Lists.newArrayList(supportedMediaTypes));
        return converter;
    }
}
@Controller
@RequestMapping("/api/history")
public class HistoricController {


    @Autowired
    public IHistoryService historyService;
    @Autowired
    public IThingService thingService;

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    public List<HistoryDTO> findHistory(@PathVariable("id") Long thingId){
        Thing thing = thingService.find(thingId);
        return historyService.findByThing(thing);
    }

}
[
    {
      "location": {
        "id": 101483,
        "name": "City A"
      },
      "dateEnteredLocation": "2016-06-06T18:44:03.000Z",
      "dateLeavingLocation": "2016-06-13T13:02:34.000Z"
    },
    {
      "location": {
        "id": 101483,
        "name": "City A"
      },
      "dateEnteredLocation": "2016-06-13T16:02:34.000Z",
      "dateLeavingLocation": "2016-06-15T11:54:57.000Z"
    },
    {
      "location": {
        "id": 101485,
        "name": "City C"
      },
      "dateEnteredLocation": "2016-06-16T04:05:06.000Z",
      "dateLeavingLocation": "2016-06-16T11:34:58.000Z"
    }
]
2016-06-06T18:44:03.000Z,2016-06-13T13:02:34.000Z,101483,City A
2016-06-13T16:02:34.000Z,2016-06-15T11:54:57.000ZZ,101483,City A
2016-06-16T04:05:06.000Z,2016-06-16T11:34:58.000Z,101485,City C
所以CSV的格式很好。但是没有包含标题。 我需要标题,使文件可以被人或机器理解

如何使jackson csv映射器自动包含标题。标题名称应与用于Json(使用Entity@Json…注释)的名称相同。


我想让它尽可能的通用。我不想为CSV编写特定的MVC控制器。

Jackson使用的机制是使用的
CsvSchema
需要启用
标题,因此类似于:

CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.emptySchema().withHeader();
String csv = mapper.writer(schema).writeValueAsString(...);

接下来的挑战是如何通过
CsvSchema
使用;或者可能的
CsvWriter
配置为使用一个。我不确定Spring MVC是否明确支持这样做。

谢谢,我在前端完成了CSV导出。这样做的主要原因是,我的大多数web API返回的深层json对象不能表示为CSV。@3是的,很难支持深层嵌套。Jackson可以用
@JsonUnwrapped
来支持它,但这会很快变得笨拙,所以实际的结构变化可能是有意义的。