diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index 08e5800bf1..48666f3bf6 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -496,6 +496,10 @@ Martin Uhlen (@MartinUhlen)
absent field same as explicit `null`
[3.2.0]
+Frederic Aubert (@f-aubert)
+ * Contributed #5745: Ability to change active JsonView on submodels (with `@JsonApplyView`)
+ [3.2.0]
+
David Nelson (@eatdrinksleepcode)
* Reported #5814: Enum deserialization does not respect
`JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_VALUES` override
diff --git a/release-notes/VERSION b/release-notes/VERSION
index fcd1e16fa8..ef01414e14 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -180,6 +180,8 @@ Versions: 3.x (for earlier see VERSION-2.x)
#5734: `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` treats
absent field same as explicit `null`
(reported by Martin U)
+#5745: Ability to change active JsonView on submodels (with `@JsonApplyView`)
+ (contributed by Frederic A)
#5821: Fix dead code and side-effect bug in `BeanPropertyWriter.toString()`
(fix by @pjfanning)
#5851: Regression of `JsonTypeInfo.Id.MINIMAL_CLASS` in the 3.x branch
diff --git a/src/main/java/tools/jackson/databind/introspect/AnnotationIntrospectorPair.java b/src/main/java/tools/jackson/databind/introspect/AnnotationIntrospectorPair.java
index e09e04eac7..dfd1565280 100644
--- a/src/main/java/tools/jackson/databind/introspect/AnnotationIntrospectorPair.java
+++ b/src/main/java/tools/jackson/databind/introspect/AnnotationIntrospectorPair.java
@@ -380,10 +380,6 @@ public Class>[] findViews(MapperConfig> config, Annotated a) {
@Override
public Class> findApplyView(MapperConfig> config, Annotated a)
{
- /* Theoretically this could be trickier, if multiple introspectors
- * return non-null entries. For now, though, we'll just consider
- * first one to return non-null to win.
- */
Class> result = _primary.findApplyView(config, a);
if (result == null) {
result = _secondary.findApplyView(config, a);
diff --git a/src/main/java/tools/jackson/databind/introspect/BeanPropertyDefinition.java b/src/main/java/tools/jackson/databind/introspect/BeanPropertyDefinition.java
index 63993e2d38..fe2f278c1f 100644
--- a/src/main/java/tools/jackson/databind/introspect/BeanPropertyDefinition.java
+++ b/src/main/java/tools/jackson/databind/introspect/BeanPropertyDefinition.java
@@ -241,6 +241,23 @@ public AnnotatedMember getNonConstructorMutator() {
*/
public Class>[] findViews() { return null; }
+ /**
+ * Method used to find an override view that should be activated when
+ * processing this property's value (and any nested values reached through
+ * it), as configured by {@code @JsonApplyView}.
+ *
+ * Unlike {@link #findViews()} (which lists views in which the property
+ * itself is included), this returns the view to make active while the
+ * value is being serialized. Special marker
+ * {@code JsonApplyView.NONE} indicates that view processing should be
+ * disabled (active view set to {@code null}) for the property and its subtree.
+ *
+ * @return Override view to apply, or {@code null} if no override is configured
+ *
+ * @since 3.2
+ */
+ public Class> findApplyView() { return null; }
+
/**
* Method used to find whether property is part of a bi-directional
* reference.
diff --git a/src/main/java/tools/jackson/databind/introspect/POJOPropertyBuilder.java b/src/main/java/tools/jackson/databind/introspect/POJOPropertyBuilder.java
index ae6e44257f..cfbee9f688 100644
--- a/src/main/java/tools/jackson/databind/introspect/POJOPropertyBuilder.java
+++ b/src/main/java/tools/jackson/databind/introspect/POJOPropertyBuilder.java
@@ -826,6 +826,11 @@ public Class>[] findViews() {
return _annotationIntrospector.findViews(_config, getPrimaryMember());
}
+ @Override
+ public Class> findApplyView() {
+ return _annotationIntrospector.findApplyView(_config, getPrimaryMember());
+ }
+
@Override
public AnnotationIntrospector.ReferenceProperty findReferenceType() {
// 30-Mar-2017, tatu: Access lazily but retain information since it needs
diff --git a/src/main/java/tools/jackson/databind/ser/BeanPropertyWriter.java b/src/main/java/tools/jackson/databind/ser/BeanPropertyWriter.java
index 23bb83232f..99363c6582 100644
--- a/src/main/java/tools/jackson/databind/ser/BeanPropertyWriter.java
+++ b/src/main/java/tools/jackson/databind/ser/BeanPropertyWriter.java
@@ -6,6 +6,7 @@
import java.lang.reflect.Field;
import java.util.HashMap;
+import com.fasterxml.jackson.annotation.JsonApplyView;
import com.fasterxml.jackson.annotation.JsonInclude;
import tools.jackson.core.JacksonException;
@@ -177,6 +178,13 @@ public class BeanPropertyWriter
*/
protected final Class>[] _includeInViews;
+ /**
+ * View to apply for this property when applyView is available for the Bean.
+ *
+ * @since 3.2
+ */
+ protected final Class> _applyView;
+
/**
* Inclusion settings for this property, pre-computed in {@code PropertyBuilder}
* by merging global defaults, type defaults, and property-level annotations,
@@ -214,13 +222,31 @@ public BeanPropertyWriter(BeanPropertyDefinition propDef,
{
this(propDef, member, contextAnnotations, declaredType,
ser, typeSer, serType, suppressNulls, suppressableValue,
- includeInViews, null);
+ includeInViews, null, null);
+ }
+
+ /**
+ * @deprecated Since 3.2 use {@link #BeanPropertyWriter(BeanPropertyDefinition,
+ * AnnotatedMember, Annotations, JavaType, ValueSerializer, TypeSerializer,
+ * JavaType, boolean, Object, Class[], JsonInclude.Value, Class)} instead.
+ */
+ @Deprecated // @since 3.2
+ public BeanPropertyWriter(BeanPropertyDefinition propDef,
+ AnnotatedMember member, Annotations contextAnnotations,
+ JavaType declaredType,
+ ValueSerializer> ser, TypeSerializer typeSer, JavaType serType,
+ boolean suppressNulls, Object suppressableValue,
+ Class>[] includeInViews, JsonInclude.Value inclusion)
+ {
+ this(propDef, member, contextAnnotations, declaredType,
+ ser, typeSer, serType, suppressNulls, suppressableValue,
+ includeInViews, inclusion, null);
}
/**
- * Constructor with additional inclusion parameter.
+ * Constructor with additional inclusion and applyView parameter.
*
- * @since 3.1
+ * @since 3.2
*/
@SuppressWarnings("unchecked")
public BeanPropertyWriter(BeanPropertyDefinition propDef,
@@ -228,7 +254,7 @@ public BeanPropertyWriter(BeanPropertyDefinition propDef,
JavaType declaredType,
ValueSerializer> ser, TypeSerializer typeSer, JavaType serType,
boolean suppressNulls, Object suppressableValue,
- Class>[] includeInViews, JsonInclude.Value inclusion)
+ Class>[] includeInViews, JsonInclude.Value inclusion, Class> applyView)
{
super(propDef);
_member = member;
@@ -260,6 +286,7 @@ public BeanPropertyWriter(BeanPropertyDefinition propDef,
// this will be resolved later on, unless nulls are to be suppressed
_nullSerializer = null;
_includeInViews = includeInViews;
+ _applyView = applyView;
_inclusion = (inclusion == null) ? JsonInclude.Value.empty() : inclusion;
}
@@ -276,6 +303,7 @@ protected BeanPropertyWriter() {
_name = null;
_wrapperName = null;
_includeInViews = null;
+ _applyView = null;
_declaredType = null;
_serializer = null;
@@ -323,6 +351,7 @@ protected BeanPropertyWriter(BeanPropertyWriter base, PropertyName name) {
_suppressNulls = base._suppressNulls;
_suppressableValue = base._suppressableValue;
_includeInViews = base._includeInViews;
+ _applyView = base._applyView;
_typeSerializer = base._typeSerializer;
_nonTrivialBaseType = base._nonTrivialBaseType;
_inclusion = base._inclusion;
@@ -347,6 +376,7 @@ protected BeanPropertyWriter(BeanPropertyWriter base, SerializedString name) {
_suppressNulls = base._suppressNulls;
_suppressableValue = base._suppressableValue;
_includeInViews = base._includeInViews;
+ _applyView = base._applyView;
_typeSerializer = base._typeSerializer;
_nonTrivialBaseType = base._nonTrivialBaseType;
_inclusion = base._inclusion;
@@ -660,10 +690,12 @@ public void serializeAsProperty(Object bean, JsonGenerator g, SerializationConte
}
}
g.writeName(_name);
- if (_typeSerializer == null) {
- ser.serialize(value, g, ctxt);
+ if (_applyView == null) {
+ _serialize(value, g, ctxt, ser);
} else {
- ser.serializeWithType(value, g, ctxt, _typeSerializer);
+ ValueSerializer