@@ -32,8 +32,11 @@ public class PropertyBuilder
32
32
/**
33
33
* If a property has serialization inclusion value of
34
34
* {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT},
35
- * we need to know the default value of the bean, to know if property value
35
+ * we may need to know the default value of the bean, to know if property value
36
36
* equals default one.
37
+ *<p>
38
+ * NOTE: only used if enclosing class defines NON_DEFAULT, but NOT if it is the
39
+ * global default OR per-property override.
37
40
*/
38
41
protected Object _defaultBean ;
39
42
@@ -110,14 +113,25 @@ protected BeanPropertyWriter buildWriter(SerializerProvider prov,
110
113
111
114
switch (inclusion ) {
112
115
case NON_DEFAULT :
113
- valueToSuppress = getDefaultValue (propDef .getName (), am );
116
+ // 11-Nov-2015, tatu: This is tricky because semantics differ between cases,
117
+ // so that if enclosing class has this, we may need to values of property,
118
+ // whereas for global defaults OR per-property overrides, we have more
119
+ // static definition. Sigh.
120
+ // First: case of class specifying it; try to find POJO property defaults
121
+ JavaType t = (serializationType == null ) ? declaredType : serializationType ;
122
+ if (_defaultInclusion .getValueInclusion () == JsonInclude .Include .NON_DEFAULT ) {
123
+ valueToSuppress = getPropertyDefaultValue (propDef .getName (), am , t );
124
+ } else {
125
+ valueToSuppress = getDefaultValue (t );
126
+ }
114
127
if (valueToSuppress == null ) {
115
128
suppressNulls = true ;
116
129
} else {
117
130
if (valueToSuppress .getClass ().isArray ()) {
118
131
valueToSuppress = ArrayBuilders .getArrayComparator (valueToSuppress );
119
132
}
120
133
}
134
+
121
135
break ;
122
136
case NON_ABSENT : // new with 2.6, to support Guava/JDK8 Optionals
123
137
// always suppress nulls
@@ -246,17 +260,24 @@ protected Object getDefaultBean()
246
260
return (def == NO_DEFAULT_MARKER ) ? null : _defaultBean ;
247
261
}
248
262
249
- protected Object getDefaultValue (String name , AnnotatedMember member )
263
+ /**
264
+ * Accessor used to find out "default value" for given property, to use for
265
+ * comparing values to serialize, to determine whether to exclude value from serialization with
266
+ * inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_EMPTY}.
267
+ * This method is called when we specifically want to know default value within context
268
+ * of a POJO, when annotation is within containing class, and not for property or
269
+ * defined as global baseline.
270
+ *<p>
271
+ * Note that returning of pseudo-type
272
+ *
273
+ * @since 2.7
274
+ */
275
+ protected Object getPropertyDefaultValue (String name , AnnotatedMember member ,
276
+ JavaType type )
250
277
{
251
278
Object defaultBean = getDefaultBean ();
252
279
if (defaultBean == null ) {
253
- // 06-Nov-2015, tatu: Returning null is fine for Object types; but need special
254
- // handling for primitives since they are never passed as nulls.
255
- Class <?> cls = member .getRawType ();
256
- if (cls .isPrimitive ()) {
257
- return ClassUtil .defaultValue (cls );
258
- }
259
- return null ;
280
+ return getDefaultValue (type );
260
281
}
261
282
try {
262
283
return member .getValue (defaultBean );
@@ -265,6 +286,38 @@ protected Object getDefaultValue(String name, AnnotatedMember member)
265
286
}
266
287
}
267
288
289
+ /**
290
+ * Accessor used to find out "default value" to use for comparing values to
291
+ * serialize, to determine whether to exclude value from serialization with
292
+ * inclusion type of {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}.
293
+ *<p>
294
+ * Default logic is such that for primitives and wrapper types for primitives, expected
295
+ * defaults (0 for `int` and `java.lang.Integer`) are returned; for Strings, empty String,
296
+ * and for structured (Maps, Collections, arrays) and reference types, criteria
297
+ * {@link com.fasterxml.jackson.annotation.JsonInclude.Include#NON_DEFAULT}
298
+ * is used.
299
+ *
300
+ * @since 2.7
301
+ */
302
+ protected Object getDefaultValue (JavaType type )
303
+ {
304
+ // 06-Nov-2015, tatu: Returning null is fine for Object types; but need special
305
+ // handling for primitives since they are never passed as nulls.
306
+ Class <?> cls = type .getRawClass ();
307
+
308
+ Class <?> prim = ClassUtil .primitiveType (cls );
309
+ if (prim != null ) {
310
+ return ClassUtil .defaultValue (prim );
311
+ }
312
+ if (type .isContainerType () || type .isReferenceType ()) {
313
+ return JsonInclude .Include .NON_EMPTY ;
314
+ }
315
+ if (cls == String .class ) {
316
+ return "" ;
317
+ }
318
+ return null ;
319
+ }
320
+
268
321
/*
269
322
/**********************************************************
270
323
/* Helper methods for exception handling
0 commit comments