Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ public AnnotatedMember getNonConstructorMutator() {
*/
public Class<?>[] findViews() { return null; }

/**
* Method used to find view to use for processing the property.
*/
public Class<?> findApplyView() { return null; }

/**
* Method used to find whether property is part of a bi-directional
* reference.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 53 additions & 10 deletions src/main/java/tools/jackson/databind/ser/BeanPropertyWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -214,21 +222,37 @@ public BeanPropertyWriter(BeanPropertyDefinition propDef,
{
this(propDef, member, contextAnnotations, declaredType,
ser, typeSer, serType, suppressNulls, suppressableValue,
includeInViews, null);
includeInViews, null, null);
}

/**
* @deprecated Since 3.2
*/
@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,
AnnotatedMember member, Annotations contextAnnotations,
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;
Expand Down Expand Up @@ -260,6 +284,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;
}

Expand All @@ -276,6 +301,7 @@ protected BeanPropertyWriter() {
_name = null;
_wrapperName = null;
_includeInViews = null;
_applyView = null;

_declaredType = null;
_serializer = null;
Expand Down Expand Up @@ -323,6 +349,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;
Expand All @@ -347,6 +374,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;
Expand Down Expand Up @@ -660,10 +688,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<Object> actualSer = ser;
ctxt.withActiveView(_applyView != JsonApplyView.NONE.class ? _applyView : null,
() -> _serialize(value, g, ctxt, actualSer));
}
}

Expand Down Expand Up @@ -728,10 +758,13 @@ public void serializeAsElement(Object bean, JsonGenerator g, SerializationContex
return;
}
}
if (_typeSerializer == null) {
ser.serialize(value, g, ctxt);

if (_applyView == null) {
_serialize(value, g, ctxt, ser);
} else {
ser.serializeWithType(value, g, ctxt, _typeSerializer);
ValueSerializer<Object> actualSer = ser;
ctxt.withActiveView(_applyView != JsonApplyView.NONE.class ? _applyView : null,
() -> _serialize(value, g, ctxt, actualSer));
}
}

Expand All @@ -753,6 +786,16 @@ public void serializeAsOmittedElement(Object bean, JsonGenerator g,
}
}

// @since 3.2
private final void _serialize(Object value, JsonGenerator g, SerializationContext ctxt,
ValueSerializer<Object> ser) {
if (_typeSerializer == null) {
ser.serialize(value, g, ctxt);
} else {
ser.serializeWithType(value, g, ctxt, _typeSerializer);
}
}

/*
/**********************************************************************
/* PropertyWriter methods (schema generation)
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/tools/jackson/databind/ser/PropertyBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,15 @@ protected BeanPropertyWriter buildWriter(SerializationContext ctxt,
if (views == null) {
views = _beanDesc.findDefaultViews();
}
Class<?> applyView = propDef.findApplyView();

// [databind#1649]: Pass the computed inclusion value (which includes
// contextual annotations) so BeanPropertyWriter can use it directly
// instead of re-computing in findPropertyInclusion()
BeanPropertyWriter bpw = _constructPropertyWriter(propDef,
am, _beanDesc.getClassAnnotations(), declaredType,
ser, typeSer, serializationType, suppressNulls, valueToSuppress, views,
inclV);
inclV, applyView);

// How about custom null serializer?
Object serDef = _annotationIntrospector.findNullSerializer(_config, am);
Expand Down Expand Up @@ -285,12 +287,12 @@ protected BeanPropertyWriter _constructPropertyWriter(BeanPropertyDefinition pro
JavaType declaredType,
ValueSerializer<?> ser, TypeSerializer typeSer, JavaType serType,
boolean suppressNulls, Object suppressableValue,
Class<?>[] includeInViews, JsonInclude.Value inclusion)
Class<?>[] includeInViews, JsonInclude.Value inclusion, Class<?> applyView)
{
return new BeanPropertyWriter(propDef,
member, contextAnnotations, declaredType,
ser, typeSer, serType, suppressNulls, suppressableValue, includeInViews,
inclusion);
inclusion, applyView);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ static class Bean
public String getB() { return "3"; }
}

static class Bean2 {

@JsonView(ViewA.class)
@JsonApplyView(ViewB.class)
public Bean bean = new Bean();

}

/**
* Bean with mix of explicitly annotated
* properties, and implicit ones that may or may
Expand Down Expand Up @@ -209,6 +217,24 @@ public void test868() throws IOException
mapper.writerWithView(OtherView.class).writeValueAsString(new Foo()));
}

// [databind#5745]: allow overriding JsonView
@Test
public void testJsonApplyView() {
// Then with "ViewA", just one property
Bean2 bean2 = new Bean2();

StringWriter sw = new StringWriter();
MAPPER.writerWithView(ViewA.class).writeValue(sw, bean2);

Map<String,Object> map = MAPPER.readValue(sw.toString(), Map.class);
assertEquals(1, map.size());
Map<String,Object> beanMap = (Map<String, Object>) map.get("bean");

assertEquals(2, beanMap.size());
assertEquals("2", beanMap.get("aa"));
assertEquals("3", beanMap.get("b"));
}

// [databind#5937]
@Test
public void testWithActiveView() throws Exception
Expand Down