Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
228bc0e
Add tests for `Record` deserialization regression and related (#3921)
JooHyukKim May 22, 2023
79c232f
Backport findPolymorphicTypeInfo
JooHyukKim May 19, 2023
8cabbd9
Clean up unnccessary change.
JooHyukKim May 19, 2023
0b30af1
Use Value class around TypeResolverBuilder
JooHyukKim May 20, 2023
a509ac2
Clean up changes
JooHyukKim May 20, 2023
97c14f1
Add version changes in StdTypeResolverBuilder
JooHyukKim May 20, 2023
3b77339
Replace usage of TypeResolverBuilder.init
JooHyukKim May 20, 2023
57b740e
Apply review
JooHyukKim May 22, 2023
04b8ed2
Add behavioral test regarding `transient` field with annotation (#3951)
JooHyukKim May 23, 2023
3505990
Update Maven wrapper version
cowtowncoder May 23, 2023
8753e8a
Merge branch '2.15' into 2.16
cowtowncoder May 23, 2023
58b9fc9
Backport `TypeResolverBuilder` initialization mechanisms from Jackson…
JooHyukKim May 23, 2023
cc02b19
remove obsolete "optimize" property
cowtowncoder May 23, 2023
a42a015
Start work on #3950: add skeletal IterationType (to merge to 3.0)
cowtowncoder May 23, 2023
dcffc41
Minor removal of deprecated "narrow" method implementation from JavaT…
cowtowncoder May 23, 2023
f878a66
...
cowtowncoder May 23, 2023
9991ffc
Backport findPolymorphicTypeInfo
JooHyukKim May 19, 2023
3cb02a4
Clean up unnccessary change.
JooHyukKim May 19, 2023
bcb1c27
Use Value class around TypeResolverBuilder
JooHyukKim May 20, 2023
0d472b3
Clean up changes
JooHyukKim May 20, 2023
8d63f67
Add version changes in StdTypeResolverBuilder
JooHyukKim May 20, 2023
94a66c6
Replace usage of TypeResolverBuilder.init
JooHyukKim May 20, 2023
3d5d2a8
Apply review
JooHyukKim May 22, 2023
c30d8a6
Remove unnccessary changes
JooHyukKim May 23, 2023
93983d3
Merge branch 'Introduce-JsonTypeInfo.Value' of https://github.com/Joo…
JooHyukKim May 23, 2023
3761d1b
Remove conflicting change in TypeResolverBuilder
JooHyukKim May 23, 2023
90edb76
Revert "Merge branch 'Introduce-JsonTypeInfo.Value' of https://github…
JooHyukKim May 23, 2023
7fdc0e7
Backport findPolymorphicTypeInfo
JooHyukKim May 19, 2023
d8d3990
Clean up unnccessary change.
JooHyukKim May 19, 2023
dd6054a
Use Value class around TypeResolverBuilder
JooHyukKim May 20, 2023
4386503
Clean up changes
JooHyukKim May 20, 2023
e628ddc
Add version changes in StdTypeResolverBuilder
JooHyukKim May 20, 2023
5e5d3b4
Replace usage of TypeResolverBuilder.init
JooHyukKim May 20, 2023
669ca81
Apply review
JooHyukKim May 22, 2023
deee3a9
Remove conflicting change in TypeResolverBuilder
JooHyukKim May 23, 2023
176d904
Revert "Merge branch 'Introduce-JsonTypeInfo.Value' of https://github…
JooHyukKim May 23, 2023
c200afd
Merge branch 'Introduce-JsonTypeInfo.Value' of https://github.com/Joo…
JooHyukKim May 23, 2023
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
11 changes: 6 additions & 5 deletions src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -1993,8 +1993,9 @@ public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv,

TypeResolverBuilder<?> typer = _constructDefaultTypeResolverBuilder(applicability, ptv);
// we'll always use full class name, when using defaulting
typer = typer.init(JsonTypeInfo.Id.CLASS, null);
typer = typer.inclusion(includeAs);
JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.CLASS, includeAs,
null, null, false, null);
typer = typer.init(typeInfo, null);
return setDefaultTyping(typer);
}

Expand Down Expand Up @@ -2023,9 +2024,9 @@ public ObjectMapper activateDefaultTypingAsProperty(PolymorphicTypeValidator ptv
TypeResolverBuilder<?> typer = _constructDefaultTypeResolverBuilder(applicability,
ptv);
// we'll always use full class name, when using defaulting
typer = typer.init(JsonTypeInfo.Id.CLASS, null);
typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
typer = typer.typeProperty(propertyName);
JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.CLASS, JsonTypeInfo.As.PROPERTY,
propertyName, null, false, null);
typer = typer.init(typeInfo, null);
return setDefaultTyping(typer);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1508,27 +1508,29 @@ protected PropertyName _findConstructorName(Annotated a)
protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config,
Annotated ann, JavaType baseType)
{
// since 2.16 : backporting {@link JsonTypeInfo.Value} from 3.0
JsonTypeInfo.Value typeInfo = findPolymorphicTypeInfo(config, ann);

// First: maybe we have explicit type resolver?
TypeResolverBuilder<?> b;
JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class);
JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class);

if (resAnn != null) {
if (info == null) {
if (typeInfo == null) {
return null;
}
// let's not try to force access override (would need to pass
// settings through if we did, since that's not doable on some platforms)
b = config.typeResolverBuilderInstance(ann, resAnn.value());
} else { // if not, use standard one, if indicated by annotations
if (info == null) {
if (typeInfo == null) {
return null;
}
// bit special; must return 'marker' to block use of default typing:
if (info.use() == JsonTypeInfo.Id.NONE) {
if (typeInfo.getIdType() == JsonTypeInfo.Id.NONE) {
return _constructNoTypeResolverBuilder();
}
b = _constructStdTypeResolverBuilder();
b = _constructStdTypeResolverBuilder(config, typeInfo, baseType);
}
// Does it define a custom type id resolver?
JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class);
Expand All @@ -1537,35 +1539,36 @@ protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config,
if (idRes != null) {
idRes.init(baseType);
}
b = b.init(info.use(), idRes);
// 13-Aug-2011, tatu: One complication; external id only works for properties;
// so if declared for a Class, we will need to map it to "PROPERTY"
// instead of "EXTERNAL_PROPERTY"
JsonTypeInfo.As inclusion = info.include();
JsonTypeInfo.As inclusion = typeInfo.getInclusionType();
if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) {
inclusion = JsonTypeInfo.As.PROPERTY;
typeInfo = typeInfo.withInclusionType(JsonTypeInfo.As.PROPERTY);
}
b = b.inclusion(inclusion);
b = b.typeProperty(info.property());
Class<?> defaultImpl = info.defaultImpl();
Class<?> defaultImpl = typeInfo.getDefaultImpl();

// 08-Dec-2014, tatu: To deprecate `JsonTypeInfo.None` we need to use other placeholder(s);
// and since `java.util.Void` has other purpose (to indicate "deser as null"), we'll instead
// use `JsonTypeInfo.class` itself. But any annotation type will actually do, as they have no
// valid use (cannot instantiate as default)
if (defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) {
b = b.defaultImpl(defaultImpl);
if (defaultImpl != null && defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) {
typeInfo = typeInfo.withDefaultImpl(defaultImpl);
}
b = b.typeIdVisibility(info.visible());

b = b.init(typeInfo, idRes);
return b;
}

/**
* Helper method for constructing standard {@link TypeResolverBuilder}
* implementation.
*
* @since 2.16, backported from 3.0
*/
protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() {
return new StdTypeResolverBuilder();
protected TypeResolverBuilder<?> _constructStdTypeResolverBuilder(MapperConfig<?> config,
JsonTypeInfo.Value typeInfo, JavaType baseType) {
return new StdTypeResolverBuilder(typeInfo);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
* handling type information embedded in JSON to allow for safe
* polymorphic type handling.
*<p>
* Builder is first initialized by calling {@link #init} method, and then
* configured using 'set' methods like {@link #inclusion}.
* Builder is first initialized by calling {@link #init(JsonTypeInfo.Value, TypeIdResolver)} method, with
* configurations passed in through {@link JsonTypeInfo.Value} that is constructed by
* {@link JsonTypeInfo.Value#construct(JsonTypeInfo.Id, As, String, Class, boolean, Boolean)}.
* Finally, after calling all configuration methods,
* {@link #buildTypeSerializer} or {@link #buildTypeDeserializer}
* will be called to get actual type resolver constructed
Expand Down Expand Up @@ -97,6 +98,24 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
* but not necessarily)
*/
public T init(JsonTypeInfo.Id idType, TypeIdResolver res);

/**
* Initialization method that is called right after constructing
* the builder instance, in cases where information could not be
* passed directly (for example when instantiated for an annotation)
* <p>
* NOTE: This method will be abstract in Jackson 3.0.
*
* @param settings Configuration settings to apply.
*
* @return Resulting builder instance (usually this builder,
* but not necessarily)
*
* @since 2.16 (backported from Jackson 3.0)
*/
default T init(JsonTypeInfo.Value settings, TypeIdResolver res) {
return init(settings.getIdType(), res);
}

/*
/**********************************************************
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.fasterxml.jackson.databind.jsontype.impl;

import com.fasterxml.jackson.databind.introspect.Annotated;
import java.util.Collection;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
Expand Down Expand Up @@ -35,6 +36,11 @@ public class StdTypeResolverBuilder
*/
protected boolean _typeIdVisible = false;

/**
* @since 2.16 (backported from Jackson 3.0)
*/
protected Boolean _requireTypeIdForSubtypes;
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think this field should be included in this PR, but #3891


/**
* Default class to use in case type information is not available
* or is broken.
Expand All @@ -53,6 +59,33 @@ public class StdTypeResolverBuilder

public StdTypeResolverBuilder() { }

/**
* @since 2.16 (backported from Jackson 3.0)
*/
public StdTypeResolverBuilder(JsonTypeInfo.Value settings) {
if (settings != null) {
_idType = settings.getIdType();
if (_idType == null) {
throw new IllegalArgumentException("idType cannot be null");
}
_includeAs = settings.getInclusionType();
_typeProperty = _propName(settings.getPropertyName(), _idType);
_typeIdVisible = settings.getIdVisible();
_defaultImpl = settings.getDefaultImpl();
_requireTypeIdForSubtypes = settings.getRequireTypeIdForSubtypes();
}
}

/**
* @since 2.16 (backported from Jackson 3.0)
*/
protected static String _propName(String propName, JsonTypeInfo.Id idType) {
if (propName == null) {
propName = idType.getDefaultPropertyName();
}
return propName;
}

/**
* @since 2.9
*/
Expand All @@ -78,10 +111,13 @@ protected StdTypeResolverBuilder(StdTypeResolverBuilder base,
_customIdResolver = base._customIdResolver;

_defaultImpl = defaultImpl;
_requireTypeIdForSubtypes = base._requireTypeIdForSubtypes;
}

public static StdTypeResolverBuilder noTypeInfoBuilder() {
return new StdTypeResolverBuilder().init(JsonTypeInfo.Id.NONE, null);
JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.NONE, null,
null, null, false, null);
return new StdTypeResolverBuilder().init(typeInfo, null);
}

@Override
Expand All @@ -98,6 +134,31 @@ public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes)
return this;
}

@Override
public StdTypeResolverBuilder init(JsonTypeInfo.Value settings,
TypeIdResolver idRes)
{
_customIdResolver = idRes;

if (settings != null) {
_idType = settings.getIdType();
if (_idType == null) {
throw new IllegalArgumentException("idType cannot be null");
}
_includeAs = settings.getInclusionType();

// Let's also initialize property name as per idType default
_typeProperty = settings.getPropertyName();
if (_typeProperty == null) {
_typeProperty = _idType.getDefaultPropertyName();
}
_typeIdVisible = settings.getIdVisible();
_defaultImpl = settings.getDefaultImpl();
_requireTypeIdForSubtypes = settings.getRequireTypeIdForSubtypes();
}
return this;
}

@Override
public TypeSerializer buildTypeSerializer(SerializationConfig config,
JavaType baseType, Collection<NamedType> subtypes)
Expand Down Expand Up @@ -436,11 +497,11 @@ protected boolean _strictTypeIdHandling(DeserializationConfig config, JavaType b
*
* @return true if the class has type resolver annotations, false otherwise
*
* @since 2.15
* @since 2.15, using {@code ai.findPolymorphicTypeInfo(config, ac)} since 2.16.
*/
protected boolean _hasTypeResolver(DeserializationConfig config, JavaType baseType) {
AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(config, baseType.getRawClass());
AnnotationIntrospector ai = config.getAnnotationIntrospector();
return ai.findTypeResolver(config, ac, baseType) != null;
return ai.findPolymorphicTypeInfo(config, ac) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,27 @@ public void testUnWrappedMapWithDefaultType() throws Exception{
assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json);
}

public void testUnWrappedMapWithDefaultTypeWithValue() throws Exception {
final ObjectMapper mapper = new ObjectMapper();
SimpleModule mod = new SimpleModule("test");
mod.addKeySerializer(ABC.class, new ABCKeySerializer());
mapper.registerModule(mod);

TypeResolverBuilder<?> typer = ObjectMapper.DefaultTypeResolverBuilder.construct(
ObjectMapper.DefaultTyping.NON_FINAL, mapper.getPolymorphicTypeValidator());
JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.NAME, JsonTypeInfo.As.PROPERTY,
null, null, true, null);
typer.init(typeInfo, null);
mapper.setDefaultTyping(typer);

Map<ABC, String> stuff = new HashMap<ABC, String>();
stuff.put(ABC.B, "bar");
String json = mapper.writerFor(new TypeReference<Map<ABC, String>>() {
})
.writeValueAsString(stuff);
assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json);
}

// [databind#1552]
public void testMapsWithBinaryKeys() throws Exception
{
Expand Down