I want to identify numerical values inserted without quotation marks (as strings) in JSON sent through the request body of a POST
request:
For example, this would be the wrong JSON format as the age field does not contain quotation marks:
{
"Student":{
"Name": "John",
"Age": 12
}
}
The correct JSON format would be:
{
"Student":{
"Name": "John",
"Age": "12"
}
}
In my code, I've defined the datatype of the age
field as a String
, hence "12"
should be the correct input. However, no error message is thrown, even when 12
is used.
It seems Jackson automatically converts the numerical values into strings. How can I identify numerical values and return a message?
This is what I tried so far to identify these numerical values:
public List<Student> getMultiple(StudentDTO Student) {
if(Student.getAge().getClass()==String.class) {
System.out.println("Age entered correctly as String");
} else{
System.out.println("Please insert age value inside inverted commas");
}
}
However, this is not printing "Please insert age value inside inverted commas"
to the console when the age is inserted without quotation marks.
If you're using Spring boot, by default it uses Jackson to parse JSON. There's no configuration option within Jackson to disable this feature, as mentioned within this issue. The solution is to register a custom JsonDeserializer
that throws an exception as soon as it encounters any other token than JsonToken.VALUE_STRING
public class StringOnlyDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
if (!JsonToken.VALUE_STRING.equals(jsonParser.getCurrentToken())) {
throw deserializationContext.wrongTokenException(jsonParser, String.class, JsonToken.VALUE_STRING, "No type conversion is allowed, string expected");
} else {
return jsonParser.getValueAsString();
}
}
}
If you only want to apply this to certain classes or fields, you can annotate those with the @JsonDeserialize
annotation. For example:
public class Student {
private String name;
@JsonDeserialize(using = StringOnlyDeserializer.class)
private String age;
// TODO: Getters + Setters
}
Alternatively, you can register a custom Jackson module by registering a SimpleModule
bean that automatically deserializes all strings using the StringOnlyDeserializer
. For example:
@Bean
public Module customModule() {
SimpleModule customModule = new SimpleModule();
customModule.addDeserializer(String.class, new StringOnlyDeserializer());
return customModule;
}
This is similar to what Eugen suggested.
If you run your application now, and you pass an invalid age, such as 12
, 12.3
or [12]
it will throw an exception with a message like:
JSON parse error: Unexpected token (VALUE_NUMBER_FLOAT), expected VALUE_STRING: Not allowed to parse numbers to string; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_NUMBER_FLOAT), expected VALUE_STRING: Not allowed to parse numbers to string\n at [Source: (PushbackInputStream); line: 3, column: 9] (through reference chain: com.example.xyz.Student[\"age\"])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With