When using Jackson framework for JSON string parsing in project development, I found a strange problem:
Deserialization is performed using the newly created ObjectMapper object. When a property of the JSON string is not defined in the Java POJO object, Throws com. Fasterxml. Jackson. Databind. Exc. UnrecognizedPropertyException anomalies.
The code is as follows:
@Data
class Person {
private String name;
private Integer age;
}
@Test
void testParseAdditionalPropWithNewMapper(a) throws JsonProcessingException {
String jsonString = "{\n" +
" \"name\": \"Alex\",\n" +
" \"age\": 18,\n" +
" \"gender\": \"MALE\"\n" +
"}";
Person person = new ObjectMapper().readValue(jsonString, Person.class);
}
Copy the code
Console output:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "gender" (class com.alex.Person), not marked as ignorable (2 known properties: "name", "age"])
at [Source: (String)"{
"name": "Alex",
"age": 18,
"gender": "MALE"
}"; line: 4, column: 16] (through reference chain: com.alex.Person["gender"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
...
Copy the code
By viewing the source code atcom.fasterxml.jackson.databind.DeserializationFeature
ClassFAIL_ON_UNKNOWN_PROPERTIES
Configuration items:
As you can see, this configuration item defines whether parsing fails when deserialization occurs when a property of the JSON string is not defined in the Java POJO object, and defaults to true.
However, when using the ObjectMapper Bean declared by SpringBoot by default, it turns out that the same scenario deserialization actually works!
@Data
class Person {
private String name;
private Integer age;
}
@SpringBootTest
@Slf4j
class JacksonParsingTests {
@Autowired
private ObjectMapper objectMapper;
@Test
void testParseAdditionalProp(a) throws JsonProcessingException {
String jsonString = "{\n" +
" \"name\": \"Alex\",\n" +
" \"age\": 18,\n" +
" \"gender\": \"MALE\"\n" +
"}";
Person person = objectMapper.readValue(jsonString, Person.class);
log.info("person: {}", person); }}Copy the code
Console output:
The 16:53:04 2021-08-13. 2116-464 the INFO [main] com. Alex. JacksonParsingTests: person: the person (name = alex, age = 18)Copy the code
The FAIL_ON_UNKNOWN_PROPERTIES configuration item value must be set to false when SpringBoot declares ObjectMapper Bean.
A Google search revealed the issue on GitHub.
Originally, in the spring – the web module org. Springframework. HTTP. Converter. Json. Jackson2ObjectMapperBuilder class, Explicit rewriting of the value of the FAIL_ON_UNKNOWN_PROPERTIES configuration item:
// Any change to this method should be also applied to spring-jms and spring-messaging
// MappingJackson2MessageConverter default constructors
private void customizeDefaultFeatures(ObjectMapper objectMapper) {...if (!this.features.containsKey(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
configureFeature(objectMapper, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); }}Copy the code
In SpringBoot ObjectMapper Bean declaration class org. Springframework. Boot. Autoconfigure. Jackson. JacksonAutoConfiguration, Reference to the above Jackson2ObjectMapperBuilder class, has carried on the ObjectMapper Bean builds, interested friends can see the source code itself.
How do I enable the FAIL_ON_UNKNOWN_PROPERTIES configuration item when using SpringBoot’s ObjectMapper Bean?
The following configuration will do the job:
spring.jackson.deserialization.fail-on-unknown-properties=true
Copy the code