在 Spring Boot 中自动将 Rest 控制器序列化为 CSV 而不是 JSON
Posted
技术标签:
【中文标题】在 Spring Boot 中自动将 Rest 控制器序列化为 CSV 而不是 JSON【英文标题】:Automatically serialize Rest controllers to CSV instead of JSON in Spring Boot 【发布时间】:2019-04-09 23:22:55 【问题描述】:我正在寻找一种快速/简单的解决方案,如何将 Rest 控制器输出自动序列化为 CSV 而不是 JSON。我有最简单的 Spring boot 应用程序:
@SpringBootApplication
public class CsvExportApplication
public static void main(String[] args)
SpringApplication.run(CsvExportApplication.class, args);
class User
String name;
String surname;
public User(String name, String surname)
this.name = name;
this.surname = surname;
public void setName(String name)
this.name = name;
public void setSurname(String surname)
this.surname = surname;
public String getName()
return name;
public String getSurname()
return surname;
@RestController
class UserController
@GetMapping(value = "/users")
List<User> list()
return Arrays.asList(new User("adam", "kowalsky"), new User("john", "smith"));
我使用了jackson-dataformat-csv
并想出了以下将List<User>
序列化为String
的代码,但理想情况下我不想更改其余控制器代码:
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(User.class).withHeader();
mapper.writerFor(List.class).with(schema).writeValueAsString(users);
理想情况下,我希望我的控制器能够根据请求中的 Accept 标头以 JSON 或 CSV 格式返回输出。
【问题讨论】:
希望这个答案可以帮助您正确定义您的休息控制器的返回格式***.com/a/33417769/8553816 【参考方案1】:我设法通过以下方式实现我想要的:
为 application/csv 定义自定义转换器 转换器只能写入CSV(不支持读取) 转换器使用 Jackon 的ObjectMapper
(以确保 CSV 和 JSON 输出使用例如相同的日期格式)
转换器即时构建jackson-dateformat-csv
模式,因为当前不支持无模式写入:https://github.com/FasterXML/jackson-dataformats-text/issues/114
代码:
class CsvConverter<T> extends AbstractHttpMessageConverter<T>
private final ObjectMapper objectMapper;
CsvConverter(ObjectMapper objectMapper)
super(new MediaType("application", "csv"));
this.objectMapper = objectMapper;
@Override
protected boolean supports(Class<?> clazz)
return true;
@Override
protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException
return null;
@Override
protected void writeInternal(T object, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException
try
ObjectWriter objectWriter = getCsvWriter(object);
try (PrintWriter outputWriter = new PrintWriter(outputMessage.getBody()))
outputWriter.write(objectWriter.writeValueAsString(object));
catch (Exception e)
throw new RuntimeException(e);
ObjectWriter getCsvWriter(T object)
Set<String> fields = getUniqueFieldNames(object);
CsvSchema.Builder schemaBuilder = CsvSchema.builder().setUseHeader(true);
for (String field : fields)
schemaBuilder.addColumn(field);
return new CsvMapper().writerFor(List.class).with(schemaBuilder.build());
Set<String> getUniqueFieldNames(T object)
try
JsonNode root = objectMapper.readTree(objectMapper.writeValueAsString(object));
Set<String> uniqueFieldNames = new LinkedHashSet<>();
root.forEach(element ->
Iterator<String> it = element.fieldNames();
while (it.hasNext())
String field = it.next();
uniqueFieldNames.add(field);
);
return uniqueFieldNames;
catch (IOException ex)
throw new RuntimeException(ex);
@Configuration
class AppConfig implements WebMvcConfigurer
private final ObjectMapper objectMapper;
AppConfig(ObjectMapper objectMapper)
this.objectMapper = objectMapper;
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters)
converters.add(new CsvConverter<>(objectMapper));
【讨论】:
以上是关于在 Spring Boot 中自动将 Rest 控制器序列化为 CSV 而不是 JSON的主要内容,如果未能解决你的问题,请参考以下文章
初入spring boot(八 )Spring Data REST
无法使用 Spring Boot 自动配置访问 REST 控制器
无法使用 Spring Boot Rest 服务将 JSON 转换为 Java 对象