Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ Project: jackson-databind
(reported by @dmelisso)
#4595: No way to explicitly disable wrapping in custom annotation processor
(reported by @SimonCockx)
#4610: `DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS` does not work when
used with Polymorphic type handling
(fix by Joo-Hyuk K)

2.17.1 (04-May-2024)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,10 @@ public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) t
// [databind#3838]: since 2.16 Uniform handling of missing objectId
// only for the specific "empty JSON Object" case
if (_objectIdReader != null && p.hasTokenId(JsonTokenId.ID_END_OBJECT)) {
ctxt.reportUnresolvedObjectId(_objectIdReader, bean);
// [databind#4610]: check if we are to skip failure
if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)) {
ctxt.reportUnresolvedObjectId(_objectIdReader, bean);
}
}
if (_injectables != null) {
injectValues(ctxt, bean);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.fasterxml.jackson.databind.objectid;

import java.util.List;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.annotation.*;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.testutil.DatabindTestUtil;

import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class ObjectIdSubTypes4610Test extends DatabindTestUtil
{
// Unused @JsonIdentityInfo
@JsonIdentityInfo(generator = ObjectIdGenerators.StringIdGenerator.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = EnumTypeDefinition.class, name = "enum"),
@JsonSubTypes.Type(value = NumberTypeDefinition.class, name = "number")
})
interface TypeDefinition {
}

static class EnumTypeDefinition implements TypeDefinition {
public List<String> values;
}

static class NumberTypeDefinition implements TypeDefinition {
}

private final ObjectMapper MAPPER = newJsonMapper();

@Test
public void shouldHandleTypeDefinitionJson() throws Exception {
String input = "{\"@type\": \"number\"}";

TypeDefinition model = MAPPER.readerFor(TypeDefinition.class)
.without(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)
.readValue(input);

Assertions.assertInstanceOf(NumberTypeDefinition.class, model);
}

@Test
public void testRoundTrip() throws Exception {
// Ser
String JSON = MAPPER.writeValueAsString(new NumberTypeDefinition());
assertTrue(JSON.contains("@id"));

// Deser
TypeDefinition model = MAPPER.readerFor(TypeDefinition.class)
.with(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)
.readValue(JSON);
Assertions.assertInstanceOf(NumberTypeDefinition.class, model);
}

@Test
public void shouldHandleTypeDefinitionJsonFail() throws Exception {
String JSON = "{\"@type\": \"number\"}";

try {
/*TypeDefinition model =*/ MAPPER.readerFor(TypeDefinition.class)
.with(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)
.readValue(JSON);
fail("Should not pass");
} catch (Exception e) {
assertTrue(e.getMessage().startsWith("No Object Id found for an instance of"));
}
}
}

This file was deleted.