jackson-jaxrs-providers
jackson-jaxrs-providers copied to clipboard
JacksonJsonProvider ignores DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS
Hello,
It seems we are facing an issue with JacksonJsonProvider that silently ignores DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS
set on the ObjectMapper.
The following test case reproduces the issue:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name", scope = Value.class)
private static class Value {
public String name;
public Integer value;
}
private static class Owned {
public String name;
public Value optionalValue;
Optional<Value> optionalValue() {
return Optional.ofNullable(optionalValue);
}
}
private static class Owner {
public List<Owned> owned = new ArrayList<>();
public List<Value> values = new ArrayList<>();
}
private final String payload = """
{
"owned": [
{ "name": "foo", "optionalValue": "vFoo" },
{ "name": "bar", "optionalValue": "this is not a valid ref to some value" },
{ "name": "baz" },
{ "name": "qux", "optionalValue": { "name": "vQux", "value": 3 } }
],
"values": [
{ "name": "vFoo", "value": 1 },
{ "name": "vBar", "value": 2 }
]
}
""";
@Test
void should_deserialize_illegal_reference_when_configured_leniently() throws JsonProcessingException {
final var objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, false);
final var owner = objectMapper.readValue(payload, Owner.class);
assertThat(owner.owned).map(o -> o.optionalValue().map(its -> its.value).orElse(null)).containsExactly(1, null, null, 3);
}
@Test
void should_reject_illegal_reference_by_default() {
final var objectMapper = new ObjectMapper();
assertThatExceptionOfType(JsonProcessingException.class).isThrownBy(() -> objectMapper.readValue(payload, Owner.class));
}
@Test
@Disabled("jackson json provider ignores object mapper configuration so this test fails")
void should_honor_mapper_configuration() throws IOException {
// Stuff to use json provider (not very friendly api)
@SuppressWarnings("unchecked")
final Class<Object> type = (Class<Object>) (Class<?>) Owner.class;
final var httpHeaders = new MultivaluedHashMap<String, String>();
final var annotations = new Annotation[] {};
final var outputStream = new ByteArrayOutputStream(4096);
outputStream.writeBytes(payload.getBytes(StandardCharsets.UTF_8));
// begin test
final var objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, true);
final var jsonProvider = new JacksonJsonProvider(objectMapper);
// Reverse comments in the following block to make the test pass despite the issue at hand
try (final var inputStream = new ByteArrayInputStream(outputStream.toByteArray())) {
assertThatExceptionOfType(JsonProcessingException.class)
.isThrownBy(() -> jsonProvider.readFrom(type, type, annotations, MediaType.APPLICATION_JSON_TYPE, httpHeaders, inputStream));
// final var object = jsonProvider.readFrom(type, type, annotations, MediaType.APPLICATION_JSON_TYPE, httpHeaders, inputStream);
// final var owner = (Owner) object;
// assertThat(owner.owned).map(o -> o.optionalValue().map(its -> its.value).orElse(null)).containsExactly(1, null, null, 3);
}
}
Thanks for your help.