gpt4 book ai didi

java - Spring Boot中的ObjectMapper可以读取字符串,但在解析 header 时不起作用

转载 作者:行者123 更新时间:2023-11-30 05:26:13 25 4
gpt4 key购买 nike

我试图将枚举值作为 header 参数提供给 Spring Boot @RestController 中的其余端点。为此,我将 Jackson 库放入我的 build.gradle 文件中,因为自动生成的枚举使用了 jackson 注释。我无法更改枚举代码(它是根据 openapi 规范自动生成的)。它看起来像这样:

public enum DocumentTypes {

APPLICATION_PDF("application/pdf"),

APPLICATION_RTF("application/rtf"),

APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT("application/vnd.oasis.opendocument.text"),

APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),

APPLICATION_VND_MS_WORD("application/vnd.ms-word"),

TEXT_HTML("text/html"),

TEXT_PLAIN("text/plain");

private String value;

DocumentTypes(String value) {
this.value = value;
}

@Override
@JsonValue
public String toString() {
return String.valueOf(value);
}

@JsonCreator
public static DocumentTypes fromValue(String text) {
for (DocumentTypes b : DocumentTypes.values()) {
if (String.valueOf(b.value).equals(text)) {
return b;
}
}
throw new IllegalArgumentException("Unexpected value '" + text + "'");
}
}

我用来测试的restcontroller看起来像这样:

@RestController
@RequestMapping("/test")
public class TestController {

@Autowired
private ObjectMapper objectMapper;

@RequestMapping(path = "", method = RequestMethod.GET)
public void test(@RequestHeader(value = "Accept", required = false) DocumentTypes targetFormat) throws IOException {
DocumentTypes value = objectMapper.readValue("\"application/pdf\"", DocumentTypes.class);
}

}

如果我不提供 Accept header ,而只是在代码中中断,我可以看到代码的第一行工作正常,application/pdf 字符串将转换为 value,因此 ObjectMapper 使用 @JsonCreator 方法完成其工作。

但是,如果我将 Accept=application/pdf header 与请求一起传递,则会收到错误:

Failed to convert value of type 'java.lang.String' to required type 'de.some.namespace.model.DocumentTypes'; 
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestHeader de.some.namespace.model.DocumentTypes] for value 'application/pdf';
nested exception is java.lang.IllegalArgumentException: No enum constant de.some.namespace.model.DocumentTypes.application/pdf"

在我看来,Spring 似乎没有使用 Jackson 提供的 ObjectMapper,因此忽略了 @JsonCreator 方法,只是尝试通过查看 if 来默认解析枚举有一个具有该提供名称的 key 。

这对我来说没有意义,因为我也只有 @Autowire ObjectMapper,...这不是 spring 也应该使用的,如何我可以强制 spring 使用正确的参数来解析参数吗?我尝试将其放入 @Configuration 中,并使其成为 @Bean@Primary ,得到相同的结果。

我有一个解决方法,通过实现转换器:

@Component
public class StringToDocumentTypesConverter implements Converter<String, DocumentTypes> {

@Autowired
private ObjectMapper mapper;

@Override
public DocumentTypes convert(String s) {
try {
return mapper.readValue(String.format("\"%s\"", s), DocumentTypes.class);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}

但我不明白为什么这是必要的,通常 spring 会自动通过 ObjectMapper 放置参数。

最佳答案

我认为这是按设计工作的。 Spring 仅使用 Jackson ObjectMapper 来转换消息体(使用注册的 HttpMessageConverter,特别是 MappingJackson2HttpMessageConverter)。

这记录在 https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-typeconversion :

Some annotated controller method arguments that represent String-based request input (such as @RequestParam, @RequestHeader, @PathVariable, @MatrixVariable, and @CookieValue) can require type conversion if the argument is declared as something other than String.

For such cases, type conversion is automatically applied based on the configured converters

https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestbody :

You can use the @RequestBody annotation to have the request body read and deserialized into an Object through an HttpMessageConverter

关于java - Spring Boot中的ObjectMapper可以读取字符串,但在解析 header 时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58543674/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com