ObjectWriterValueToTree5710Test.java
package tools.jackson.databind;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.testutil.DatabindTestUtil;
import static org.junit.jupiter.api.Assertions.*;
// [databind#5710]: ObjectWriter.valueToTree() generates incomplete tree model
// for polymorphic types when wrapped in container/reference types
class ObjectWriterValueToTree5710Test extends DatabindTestUtil
{
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "subtype", value = Subtype.class)
})
interface Supertype {}
@JsonTypeName("subtype")
static class Subtype implements Supertype {
public String content = "hello";
}
private final ObjectMapper MAPPER = newJsonMapper();
// Direct polymorphic type: valueToTree() should include "@type" property
@Test
void valueToTreeDirectPolymorphicType() throws Exception
{
ObjectWriter writer = MAPPER.writerFor(new TypeReference<Supertype>() {});
Subtype value = new Subtype();
JsonNode tree = writer.valueToTree(value);
assertTrue(tree.has("@type"), "Expected '@type' property in tree for direct polymorphic type");
assertEquals("subtype", tree.get("@type").asString());
assertEquals("hello", tree.get("content").asString());
}
// List-wrapped polymorphic type: valueToTree() should include "@type" in array elements
@Test
void valueToTreeListWrappedPolymorphicType() throws Exception
{
ObjectWriter writer = MAPPER.writerFor(new TypeReference<List<Supertype>>() {});
List<Subtype> value = List.of(new Subtype());
// writeValueAsString() works correctly
String json = writer.writeValueAsString(value);
assertTrue(json.contains("\"@type\""), "writeValueAsString() should include '@type': " + json);
// valueToTree() should match writeValueAsString()
assertEquals(MAPPER.readTree(json), writer.valueToTree(value),
"valueToTree() should match writeValueAsString() for List<Supertype>");
}
// Optional-wrapped polymorphic type: valueToTree() should include "@type" property
@Test
void valueToTreeOptionalWrappedPolymorphicType() throws Exception
{
ObjectWriter writer = MAPPER.writerFor(new TypeReference<Optional<Supertype>>() {});
Optional<Subtype> value = Optional.of(new Subtype());
// writeValueAsString() works correctly
String json = writer.writeValueAsString(value);
assertTrue(json.contains("\"@type\""), "writeValueAsString() should include '@type': " + json);
// valueToTree() should match writeValueAsString()
assertEquals(MAPPER.readTree(json), writer.valueToTree(value),
"valueToTree() should match writeValueAsString() for Optional<Supertype>");
}
}