java - Spring Boot CsvMapper bean 在返回使用 Map 创建的 ResponseEntity 时会导致错误
问题描述
在我的 Spring Boot 应用程序中,我有一个注入到 Service 类中的 CsvMapper。这个 CsvMapper 被定义为 Config 文件中的一个 bean。
在我的控制器中,当我返回一个通过传入 HashMap 创建的 ResponseEntity 时,堆栈跟踪会显示这些错误。
w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Unrecognized column 'message': known columns: ]; nested exception is com.fasterxml.jackson.dataformat.csv.CsvMappingException: Unrecognized column 'message': known columns: ] (through reference chain: java.util.HashMap["message"])]
w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Unrecognized column 'timestamp': known columns: ]; nested exception is com.fasterxml.jackson.dataformat.csv.CsvMappingException: Unrecognized column 'timestamp': known columns: ] (through reference chain: java.util.LinkedHashMap["timestamp"])]
以下是这些文件的简要布局。
CSVParserService
@Slf4j
@Component
public final class CsvParserService {
private CsvMapper csvMapper;
// TODO: This injection causes a problem when creating a ResponseEntity(Map,...). Investigate why this is happening
public CsvParserService(@Qualifier("myCsvMapper") CsvMapper myCsvMapper) {
this.csvMapper = myCsvMapper;
}
public <T> List<T> parseCsvFile(Class<T> modelClass, MultipartFile csvFile, boolean ifHeader) throws IOException {
// create inputStream of the scorecard CSV file
InputStream fileStream = new BufferedInputStream(csvFile.getInputStream());
CsvSchema csvSchema = csvMapper
.typedSchemaFor(modelClass)
.withUseHeader(ifHeader) // this should be configured applied based on the queryParameter value in the PostRequest
.withColumnSeparator(',')
.sortedBy("timestamp", "productName", "a", "b", "c", "d", "e", "f", "g", "h", "j", "k");
MappingIterator<T> iterator = csvMapper
.readerWithTypedSchemaFor(modelClass)
.with(csvSchema)
.readValues(fileStream);
return iterator.readAll();
}
定义 bean 的 Config 文件
@Configuration
public class JacksonConfig {
@Bean(name="myCsvMapper")
public CsvMapper myCsvMapper(DateTimeFormatter dateTimeFormatter) {
JavaTimeModule javaTimeModule = new JavaTimeModule();
configureDateTimeDeSerialization(javaTimeModule, dateTimeFormatter);
CsvMapper csvMapper = new CsvMapper();
csvMapper.registerModule(javaTimeModule);
return csvMapper;
}
private void configureDateTimeDeSerialization(JavaTimeModule javaTimeModule, DateTimeFormatter dateTimeFormatter) {
// Instant customizations
javaTimeModule.addSerializer(Instant.class, new JsonSerializer<>() {
@Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(dateTimeFormatter.format(value));
}
});
javaTimeModule.addDeserializer(Instant.class, new JsonDeserializer<>() {
@Override
public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return dateTimeFormatter.parse(p.getText(), Instant::from);
}
});
// Instant customizations for map keys
javaTimeModule.addKeySerializer(Instant.class, new JsonSerializer<>() {
@Override
public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeFieldName(dateTimeFormatter.format(value));
}
});
javaTimeModule.addKeyDeserializer(Instant.class, new KeyDeserializer() {
@Override
public Object deserializeKey(String key, DeserializationContext ctxt) {
return dateTimeFormatter.parse(key, Instant::from);
}
});
}
发生错误的控制器在“return new...”的行上
@RepositoryRestController
@RequestMapping("/api/v1")
public class ScorecardSummaryController {
@ResponseBody
@GetMapping(value = {"/csvmapper"})
public ResponseEntity<?> getProducts() {
// some services calls
Map<String, String> map = new HashMap<String, String>();
map.put("message", "Some message");
map.put("status", "Ok");
return new ResponseEntity<>(map, HttpStatus.OK); // error occurs after this line
}
}
我怀疑 CsvMapper bean 已成为应用程序的默认映射器?但是我不确定在通过传入 HashMap 创建 ResponseEntity 时会发生这种情况或为什么会发生这种情况。如果我以另一种方式创建 ResponseEntity,例如
return new ResponseEntity<String>("Success", HttpStatus.OK);
,它不会返回任何错误。如果我在 @Bean 定义中编写代码以忽略未知列的错误,则当我点击 API 端点时应用程序不会返回任何内容”。
解决方案
推荐阅读
- bash - 我怎样才能在 bash 中获得昨天的朱利安日期?
- c++ - 请证明这个执行的合理性 c++
- r - 选择最大日期的列名
- javascript - 在 html5 中构建表单时如何显示警告标志?
- c++ - Integrity OS 上的 dladdr 类似物?
- android - BuildConfig 无法从变量中正确创建值(Gradle Android)
- sql - DB2 join with case when 和最近的时间戳
- angular - 如何在 Mat-Toolbar 中选择单击的链接
- javascript - 如何在没有任何空格的 URL 中托管 JSON 文件?
- discord.js - 加入 enmap 时的自定义角色