3
3
import java .io .IOException ;
4
4
import java .util .Optional ;
5
5
6
+ import com .fasterxml .jackson .annotation .JsonInclude ;
7
+
6
8
import com .fasterxml .jackson .core .JsonGenerator ;
9
+
7
10
import com .fasterxml .jackson .databind .*;
8
11
import com .fasterxml .jackson .databind .annotation .JsonSerialize ;
9
12
import com .fasterxml .jackson .databind .introspect .Annotated ;
@@ -35,14 +38,28 @@ public class OptionalSerializer
35
38
*/
36
39
protected final NameTransformer _unwrapper ;
37
40
41
+ /**
42
+ * Further guidance on serialization-inclusion (or not), regarding
43
+ * contained value (if any).
44
+ *
45
+ * @since 2.7
46
+ */
47
+ protected final JsonInclude .Include _contentInclusion ;
48
+
38
49
/**
39
50
* If element type can not be statically determined, mapping from
40
51
* runtime type to serializer is handled using this object
41
52
*
42
53
* @since 2.6
43
54
*/
44
55
protected transient PropertySerializerMap _dynamicSerializers ;
45
-
56
+
57
+ /*
58
+ /**********************************************************
59
+ /* Constructors, factory methods
60
+ /**********************************************************
61
+ */
62
+
46
63
public OptionalSerializer (JavaType type ) {
47
64
this (type , null );
48
65
}
@@ -55,30 +72,57 @@ protected OptionalSerializer(JavaType optionalType, JsonSerializer<?> valueSer)
55
72
_property = null ;
56
73
_valueSerializer = (JsonSerializer <Object >) valueSer ;
57
74
_unwrapper = null ;
75
+ _contentInclusion = null ;
58
76
_dynamicSerializers = PropertySerializerMap .emptyForProperties ();
59
77
}
60
78
61
79
@ SuppressWarnings ("unchecked" )
62
80
protected OptionalSerializer (OptionalSerializer base ,
63
- BeanProperty property , JsonSerializer <?> valueSer , NameTransformer unwrapper )
81
+ BeanProperty property , JsonSerializer <?> valueSer , NameTransformer unwrapper ,
82
+ JsonInclude .Include contentIncl )
64
83
{
65
84
super (base );
66
85
_referredType = base ._referredType ;
67
86
_dynamicSerializers = base ._dynamicSerializers ;
68
87
_property = property ;
69
88
_valueSerializer = (JsonSerializer <Object >) valueSer ;
70
89
_unwrapper = unwrapper ;
90
+ if ((contentIncl == JsonInclude .Include .USE_DEFAULTS )
91
+ || (contentIncl == JsonInclude .Include .ALWAYS )) {
92
+ _contentInclusion = null ;
93
+ } else {
94
+ _contentInclusion = contentIncl ;
95
+ }
71
96
}
72
97
98
+ @ Override
99
+ public JsonSerializer <Optional <?>> unwrappingSerializer (NameTransformer transformer ) {
100
+ JsonSerializer <Object > ser = _valueSerializer ;
101
+ if (ser != null ) {
102
+ ser = ser .unwrappingSerializer (transformer );
103
+ }
104
+ NameTransformer unwrapper = (_unwrapper == null ) ? transformer
105
+ : NameTransformer .chainedTransformer (transformer , _unwrapper );
106
+ return withResolved (_property , ser , unwrapper , _contentInclusion );
107
+ }
108
+
73
109
protected OptionalSerializer withResolved (BeanProperty prop ,
74
- JsonSerializer <?> ser , NameTransformer unwrapper )
110
+ JsonSerializer <?> ser , NameTransformer unwrapper ,
111
+ JsonInclude .Include contentIncl )
75
112
{
76
- if ((_property == prop ) && (_valueSerializer == ser ) && (_unwrapper == unwrapper )) {
113
+ if ((_property == prop ) && (contentIncl == _contentInclusion )
114
+ && (_valueSerializer == ser ) && (_unwrapper == unwrapper )) {
77
115
return this ;
78
116
}
79
- return new OptionalSerializer (this , prop , ser , unwrapper );
117
+ return new OptionalSerializer (this , prop , ser , unwrapper , contentIncl );
80
118
}
81
119
120
+ /*
121
+ /**********************************************************
122
+ /* Contextualization (support for property annotations)
123
+ /**********************************************************
124
+ */
125
+
82
126
@ Override
83
127
public JsonSerializer <?> createContextual (SerializerProvider provider ,
84
128
BeanProperty property ) throws JsonMappingException
@@ -92,20 +136,38 @@ public JsonSerializer<?> createContextual(SerializerProvider provider,
92
136
} else {
93
137
ser = provider .handlePrimaryContextualization (ser , property );
94
138
}
95
- return withResolved (property , ser , _unwrapper );
139
+ // Also: may want to have more refined exclusion based on referenced value
140
+ JsonInclude .Include contentIncl = _contentInclusion ;
141
+ if (property != null ) {
142
+ AnnotationIntrospector intr = provider .getAnnotationIntrospector ();
143
+ if (intr != null ) {
144
+ JsonInclude .Value incl = intr .findPropertyInclusion (property .getMember ());
145
+ if (incl != null ) {
146
+ JsonInclude .Include newIncl = incl .getContentInclusion ();
147
+ if ((newIncl != contentIncl ) && (newIncl != JsonInclude .Include .NON_DEFAULT )) {
148
+ contentIncl = newIncl ;
149
+ }
150
+ }
151
+ }
152
+ }
153
+ return withResolved (property , ser , _unwrapper , contentIncl );
96
154
}
97
155
98
156
protected boolean _useStatic (SerializerProvider provider , BeanProperty property ,
99
157
JavaType referredType )
100
158
{
101
159
// First: no serializer for `Object.class`, must be dynamic
102
- if (_referredType .hasRawClass ( Object . class )) {
160
+ if (_referredType .isJavaLangObject ( )) {
103
161
return false ;
104
162
}
105
163
// but if type is final, might as well fetch
106
164
if (_referredType .isFinal ()) { // or should we allow annotation override? (only if requested...)
107
165
return true ;
108
166
}
167
+ // also: if indicated by typing, should be considered static
168
+ if (_referredType .useStaticType ()) {
169
+ return true ;
170
+ }
109
171
// if neither, maybe explicit annotation?
110
172
AnnotationIntrospector intr = provider .getAnnotationIntrospector ();
111
173
if ((intr != null ) && (property != null )) {
@@ -124,15 +186,36 @@ protected boolean _useStatic(SerializerProvider provider, BeanProperty property,
124
186
return provider .isEnabled (MapperFeature .USE_STATIC_TYPING );
125
187
}
126
188
189
+ /*
190
+ /**********************************************************
191
+ /* API overrides
192
+ /**********************************************************
193
+ */
194
+
127
195
@ Override
128
- public JsonSerializer <Optional <?>> unwrappingSerializer (NameTransformer transformer ) {
196
+ public boolean isEmpty (SerializerProvider provider , Optional <?> value )
197
+ {
198
+ if ((value == null ) || !value .isPresent ()) {
199
+ return true ;
200
+ }
201
+ if (_contentInclusion == null ) {
202
+ return false ;
203
+ }
204
+ Object contents = value .get ();
129
205
JsonSerializer <Object > ser = _valueSerializer ;
130
- if (ser != null ) {
131
- ser = ser .unwrappingSerializer (transformer );
206
+ if (ser == null ) {
207
+ try {
208
+ ser = _findCachedSerializer (provider , value .getClass ());
209
+ } catch (JsonMappingException e ) { // nasty but necessary
210
+ throw new RuntimeJsonMappingException (e );
211
+ }
132
212
}
133
- NameTransformer unwrapper = (_unwrapper == null ) ? transformer
134
- : NameTransformer .chainedTransformer (transformer , _unwrapper );
135
- return withResolved (_property , ser , unwrapper );
213
+ return ser .isEmpty (provider , contents );
214
+ }
215
+
216
+ @ Override
217
+ public boolean isUnwrappingSerializer () {
218
+ return (_unwrapper != null );
136
219
}
137
220
138
221
/*
@@ -174,22 +257,6 @@ public void serializeWithType(Optional<?> opt,
174
257
}
175
258
}
176
259
177
- /*
178
- /**********************************************************
179
- /* API overrides
180
- /**********************************************************
181
- */
182
-
183
- @ Override
184
- public boolean isEmpty (SerializerProvider provider , Optional <?> value ) {
185
- return (value == null ) || !value .isPresent ();
186
- }
187
-
188
- @ Override
189
- public boolean isUnwrappingSerializer () {
190
- return (_unwrapper != null );
191
- }
192
-
193
260
/*
194
261
/**********************************************************
195
262
/* Introspection support
0 commit comments