Reputation: 113
I have created my request POJO as follows
@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;
when I send request body as follow, it is working fine.
{
"clientId":"9563",
"userId":"5855541",
"requestingService":"cm-dm-service",
"message":"Document Created",
"messageType":"user-msg"
}
But when I sent like below
{
"clientId":"9563",
"userId":true,
"requestingService":"cm-dm-service",
"message":"Document Created",
"messageType":"user-msg"
}
Here is my controller
public ResponseEntity<Status> createNotification(@RequestBody @Valid Notification notification,
BindingResult bindingResult, HttpServletRequest request) throws AppException {
Expected: throw some error
Actual: converting true value for userId to string by jackson.
please let me know is there a way to acheive the Expected behaviour
Upvotes: 3
Views: 1884
Reputation: 71
The jackson NumberDeserializers.BooleanDeserializer
is programmed to convert boolean to String.
We can override the deserializer with ours and prevent the conversion and throw an exception instead.
I can give you an example, you try to implement it to your problem statement.
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);
}
}
Upvotes: 2
Reputation: 38635
By default, com.fasterxml.jackson.databind.deser.std.StringDeserializer
accepts scalar values. You can implement custom deserialiser and throw exception in this case:
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);
}
}
To register it use SimpleModule
:
SimpleModule strictModule = new SimpleModule();
strictModule.addDeserializer(String.class, new StrictStringDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(strictModule);
To how to do that in Spring
read: Customize the Jackson ObjectMapper.
If you only want to change it for a one field: userId
use JsonDeserialize
annotation:
@JsonDeserialize(using = StrictStringDeserializer.class)
private String userId;
See also:
Upvotes: 2