在 Spring boot 2.4 (Jackson) 中将字符串数据类型限制为请求主体的字符串类型
Restrict string data type to only string types for request body in Spring boot 2.4 (Jackson)
我已经创建了我的请求 POJO,如下所示
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Notification {
@NotNull
private String clientId;
private String userId;
@NotNull
private String requestingService;
@NotNull
private String message;
@NotNull
private String messageType;
当我如下发送请求正文时,它工作正常。
{
"clientId":"9563",
"userId":"5855541",
"requestingService":"cm-dm-service",
"message":"Document Created",
"messageType":"user-msg"
}
但是当我像下面这样发送时
{
"clientId":"9563",
"userId":true,
"requestingService":"cm-dm-service",
"message":"Document Created",
"messageType":"user-msg"
}
这是我的控制器
public ResponseEntity<Status> createNotification(@RequestBody @Valid Notification notification,
BindingResult bindingResult, HttpServletRequest request) throws AppException {
预期:抛出一些错误
实际:通过 jackson 将 userId 的 true 值转换为字符串。
请告诉我有没有办法实现预期行为
jackson NumberDeserializers.BooleanDeserializer
被编程为将布尔值转换为字符串。
我们可以用我们的反序列化器覆盖并阻止转换并抛出异常。
我可以给你一个例子,你试着把它实现到你的问题陈述中。
- 创建布尔反序列化 class
public class MyDeser extends JsonDeserializer {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken t = p.getCurrentToken();
if (t.isBoolean()) {
throw new Exception();
}
else if (t.isNumeric()) {
throw new Exception();
}
else if (t == JsonToken.VALUE_STRING) {
return p.getValueAsString();
}
return null;
}
}
- 现在将解串器注入我们的应用程序
@SpringBootApplication
@Configuration
public class Application {
@Bean
public SimpleModule injectDeser() {
return new SimpleModule().addDeserializer(String.class, new MyDeser());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
默认情况下,com.fasterxml.jackson.databind.deser.std.StringDeserializer
接受标量值。在这种情况下,您可以实现自定义反序列化器并抛出异常:
class StrictStringDeserializer extends StringDeserializer {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonToken token = p.currentToken();
if (token.isScalarValue()) {
ctxt.reportInputMismatch(String.class, "%s is not a `String` value!", token.toString());
return null;
}
return super.deserialize(p, ctxt);
}
}
要注册它,请使用 SimpleModule
:
SimpleModule strictModule = new SimpleModule();
strictModule.addDeserializer(String.class, new StrictStringDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(strictModule);
如何在 Spring
阅读:Customize the Jackson ObjectMapper。
如果您只想更改一个字段:userId
使用 JsonDeserialize
注释:
@JsonDeserialize(using = StrictStringDeserializer.class)
private String userId;
另请参阅:
我已经创建了我的请求 POJO,如下所示
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Notification {
@NotNull
private String clientId;
private String userId;
@NotNull
private String requestingService;
@NotNull
private String message;
@NotNull
private String messageType;
当我如下发送请求正文时,它工作正常。
{
"clientId":"9563",
"userId":"5855541",
"requestingService":"cm-dm-service",
"message":"Document Created",
"messageType":"user-msg"
}
但是当我像下面这样发送时
{
"clientId":"9563",
"userId":true,
"requestingService":"cm-dm-service",
"message":"Document Created",
"messageType":"user-msg"
}
这是我的控制器
public ResponseEntity<Status> createNotification(@RequestBody @Valid Notification notification,
BindingResult bindingResult, HttpServletRequest request) throws AppException {
预期:抛出一些错误
实际:通过 jackson 将 userId 的 true 值转换为字符串。
请告诉我有没有办法实现预期行为
jackson NumberDeserializers.BooleanDeserializer
被编程为将布尔值转换为字符串。
我们可以用我们的反序列化器覆盖并阻止转换并抛出异常。
我可以给你一个例子,你试着把它实现到你的问题陈述中。
- 创建布尔反序列化 class
public class MyDeser extends JsonDeserializer {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonToken t = p.getCurrentToken();
if (t.isBoolean()) {
throw new Exception();
}
else if (t.isNumeric()) {
throw new Exception();
}
else if (t == JsonToken.VALUE_STRING) {
return p.getValueAsString();
}
return null;
}
}
- 现在将解串器注入我们的应用程序
@SpringBootApplication
@Configuration
public class Application {
@Bean
public SimpleModule injectDeser() {
return new SimpleModule().addDeserializer(String.class, new MyDeser());
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
默认情况下,com.fasterxml.jackson.databind.deser.std.StringDeserializer
接受标量值。在这种情况下,您可以实现自定义反序列化器并抛出异常:
class StrictStringDeserializer extends StringDeserializer {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonToken token = p.currentToken();
if (token.isScalarValue()) {
ctxt.reportInputMismatch(String.class, "%s is not a `String` value!", token.toString());
return null;
}
return super.deserialize(p, ctxt);
}
}
要注册它,请使用 SimpleModule
:
SimpleModule strictModule = new SimpleModule();
strictModule.addDeserializer(String.class, new StrictStringDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(strictModule);
如何在 Spring
阅读:Customize the Jackson ObjectMapper。
如果您只想更改一个字段:userId
使用 JsonDeserialize
注释:
@JsonDeserialize(using = StrictStringDeserializer.class)
private String userId;
另请参阅: