skip to Main Content

Deserialisation should fail for the following POJO if the json has an additional field, as the Jackson documentation says FAIL_ON_UKNOWN_PROPERTIES is set by default.

@Getter
@Setter
@FieldNameConstants
@ToString
@Builder
@Document(collection = "form_layouts")
@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true)
@Jacksonized
public class MyFormLayout extends AuditableDocument {

    @NotNull
    private Boolean selected;
    @NotNull
    private Boolean disabled;
    @NotEmpty
    private List<Layout> layout;

    @NotBlank
    @EqualsAndHashCode.Include
    private String realmId;
}

I was expecting this test to fail with UnrecognizedPropertyException which it doesn’t even after setting this property on Jackson

@SpringJUnitConfig
@TestPropertySource(
        properties = {
                "spring.jackson.deserialization.fail-on-unknown-properties=true"
        }
)
@AutoConfigureJson
@DisplayName("Form Layout Deserialisation")
public class MyFormLayoutDeserialisationTest {

    @Autowired
    Jackson2ObjectMapperBuilder objectMapperBuilder;
    ObjectMapper objectMapper;

    @BeforeEach
    void setUp() {
        objectMapper = objectMapperBuilder.build();
    }

    @Test
    @DisplayName("fails loading seeder json if the keys don't match to object fields")
    void testForcesJsonToMatchFormTemplate(@Value("classpath:bad_nform_layout.json") Resource badLayout) {
        Assertions.assertThrows(UnrecognizedPropertyException.class, () -> objectMapper.readValue(Files.readString(Path.of(badLayout.getFile().getAbsolutePath())), new TypeReference<>() {
        }), "Seeder JSON should have the exact keys and fields declared in the MyFormLayout object");
    }
}

Test fails with the message

org.opentest4j.AssertionFailedError: Seeder JSON should have the exact keys and fields declared in the MyFormLayout object ==> Expected com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException to be thrown, but nothing was thrown.

the JSON file

[
  {
    "selected": false,
    "disabled": true,
    "app": "blox",
    "foo": "bar",
    "layout": [
      {
        "id": "B-1",
        "x": 0,
        "y": 0,
        "w": 12,
        "h": 7
      },
      {
        "id": "B-2",
        "x": 13,
        "y": 0,
        "w": 4,
        "h": 4
      },
      {
        "id": "B-3",
        "x": 0,
        "y": 8,
        "w": 12,
        "h": 3
      },
      {
        "id": "B-4",
        "x": 13,
        "y": 5,
        "w": 4,
        "h": 6
      }
    ]
  }
  ...
]

"foo": "bar" is the unknown property that should have failed deserialisation.

2

Answers


  1. Chosen as BEST ANSWER

    Changed the type reference to new TypeReference<List<MyFormTemplate>>() {} fixed it.


    1. Annotation Effects: Make sure that annotations like @Jacksonized
      from Lombok are not altering the default behavior of the
      ObjectMapper, particularly concerning the handling of unknown
      properties.

    2. Example of a Global ObjectMapper Bean with Feature Enabled: You can
      create an ObjectMapper bean with the FAIL_ON_UNKNOWN_PROPERTIES
      feature enabled and use it throughout your application. Here’s how
      to do it in a Spring Boot @Configuration class:

      @Configuration
      public class MyConfiguration {

          @Bean
          public ObjectMapper objectMapper() {
              ObjectMapper objectMapper = new ObjectMapper();
              objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
              return objectMapper;
          }
      }
      
    3. JunitTest isolate:

       @Test
       @DisplayName("GIVEN a JSON string with unknown properties WHEN deserialized THEN should throw UnrecognizedPropertyException")
       void debugTest() {
           ObjectMapper localMapper = new ObjectMapper();
           localMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
      
           String jsonString = "{"selected": false, "disabled": true, "foo": "bar"}";
      
           Assertions.assertThrows(
               UnrecognizedPropertyException.class,
               () -> localMapper.readValue(jsonString, MyFormLayout.class)
           );
       }
      
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search