Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tools.jackson.databind.jsontype.impl;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;

import tools.jackson.core.JacksonException;
Expand Down Expand Up @@ -169,8 +170,10 @@ protected Object _deserializeTypedUsingDefaultImpl(JsonParser p,
// genuine, or faked for "dont fail on bad type id")
ValueDeserializer<Object> deser = _findDefaultImplDeserializer(ctxt);
if (deser == null) {
JavaType t = _strictTypeIdHandling
? _handleMissingTypeId(ctxt, priorFailureMsg) : _baseType;
JavaType t = isStrictTypeIdHandlingForProperty()
? _handleMissingTypeId(ctxt, priorFailureMsg)
: _baseType;

if (t == null) {
// 09-Mar-2017, tatu: Is this the right thing to do?
return null;
Expand Down Expand Up @@ -203,6 +206,17 @@ public Object deserializeTypedFromAny(JsonParser p, DeserializationContext ctxt)
return deserializeTypedFromObject(p, ctxt);
}

// [databind#1654]: Determine whether strict type-id handling should apply for this property.
private boolean isStrictTypeIdHandlingForProperty() {
if (!_strictTypeIdHandling) {
return false;
}
if (_property == null) {
return true;
}
JsonTypeInfo typeInfo = _property.getAnnotation(JsonTypeInfo.class);
Copy link
Member

@cowtowncoder cowtowncoder Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too expensive call to make during actual reading -- that information needs to be gathered when constructing or initializing TypeDeserializer instance.

Also: direct annotation access should be avoided: all access must be through AnnotationIntrospector (to allow for mix-in annotations, support for non-Jackson annotations (like JAXB))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the kind explanation :)

I’ll review the changes you suggested in the PR and update my work accordingly
#5477

return typeInfo == null || typeInfo.use() != JsonTypeInfo.Id.NONE;
}
// These are fine from base class:
//public Object deserializeTypedFromArray(JsonParser p, DeserializationContext ctxt)
//public Object deserializeTypedFromScalar(JsonParser p, DeserializationContext ctxt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ public WritableTypeId writeTypePrefix(JsonGenerator g, SerializationContext ctxt
WritableTypeId idMetadata) throws JacksonException
{
_generateTypeId(ctxt, idMetadata);

// [databind#1654]: If the property overrides type info with @JsonTypeInfo(use = NONE),
// skip writing a type id for this property.
if (_property != null) {
JsonTypeInfo typeInfo = _property.getAnnotation(JsonTypeInfo.class);
if (typeInfo != null && typeInfo.use() == JsonTypeInfo.Id.NONE) {
idMetadata.id = null;
}
}

// 16-Jan-2022, tatu: As per [databind#3373], skip for null typeId.
// And return "null" to avoid matching "writeTypeSuffix" as well.
// 15-Jun-2024, tatu: [databind#4407] Not so fast! Output wrappers
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tools.jackson.databind.tofix;
package tools.jackson.databind;

import java.util.*;

Expand All @@ -7,10 +7,8 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import tools.jackson.core.JsonParser;
import tools.jackson.databind.*;
import tools.jackson.databind.annotation.JsonDeserialize;
import tools.jackson.databind.testutil.DatabindTestUtil;
import tools.jackson.databind.testutil.failure.JacksonTestFailureExpected;

import static org.junit.jupiter.api.Assertions.assertEquals;

Expand Down Expand Up @@ -77,24 +75,22 @@ void noTypeElementOverride() throws Exception {
}

// [databind#1654]
@JacksonTestFailureExpected
@Test
void noTypeInfoOverrideSer() throws Exception {
Value1654UntypedContainer cont = new Value1654UntypedContainer(
new Value1654(3),
new Value1654(7)
);
assertEquals(a2q("{'values':[{'x':3},{'x': 7}] }"),
assertEquals(a2q("{'values':[{'x':3},{'x':7}]}"),
MAPPER.writeValueAsString(cont));
}

// [databind#1654]
@JacksonTestFailureExpected
@Test
void noTypeInfoOverrideDeser() throws Exception {
// and then actual failing case
final String noTypeJson = a2q(
"{'values':[{'x':3},{'x': 7}] }"
"{'values':[{'x':3},{'x':7}]}"
);
Value1654UntypedContainer unResult = MAPPER.readValue(noTypeJson, Value1654UntypedContainer.class);
assertEquals(2, unResult.values.size());
Expand Down