6767public @interface JsonTypeInfo
6868{
6969 /*
70- /**********************************************************
70+ /**********************************************************************
7171 /* Value enumerations used for properties
72- /**********************************************************
72+ /**********************************************************************
7373 */
7474
7575 /**
@@ -256,9 +256,9 @@ public enum As {
256256 }
257257
258258 /*
259- /**********************************************************
259+ /**********************************************************************
260260 /* Annotation properties
261- /**********************************************************
261+ /**********************************************************************
262262 */
263263
264264 /**
@@ -339,23 +339,6 @@ public enum As {
339339 */
340340 public boolean visible () default false ;
341341
342- /*
343- /**********************************************************
344- /* Helper classes
345- /**********************************************************
346- */
347-
348- /**
349- * This marker class that is only to be used with <code>defaultImpl</code>
350- * annotation property, to indicate that there is no default implementation
351- * specified.
352- *
353- * @deprecated Since 2.5, use any Annotation type (such as {@link JsonTypeInfo}),
354- * if such behavior is needed; this is rarely necessary.
355- */
356- @ Deprecated // since 2.5
357- public abstract static class None {}
358-
359342 /**
360343 * Specifies whether the type ID should be strictly required during polymorphic
361344 * deserialization of its subtypes.
@@ -374,6 +357,44 @@ public abstract static class None {}
374357 */
375358 public OptBoolean requireTypeIdForSubtypes () default OptBoolean .DEFAULT ;
376359
360+ /**
361+ * Property that defines whether serialization of type id should be done
362+ * when the runtime type of the value is the same as {@link #defaultImpl()}.
363+ * Skipping write can be useful since during deserialization, if no type id is present,
364+ * {@code defaultImpl} is used as the fallback type -- so the type id is redundant
365+ * for that type.
366+ *<p>
367+ * When disabled ({@link OptBoolean#FALSE}), the type id will NOT be written
368+ * if the actual runtime class of the value exactly matches {@code defaultImpl}.
369+ * Subclasses of {@code defaultImpl} will still have their type id written.
370+ *<p>
371+ * NOTE: support for this feature is only added in Jackson 3.x, specifically
372+ * 3.2. It is not supported by Jackson 2.x.
373+ *<p>
374+ * Default value is {@link OptBoolean#DEFAULT} (which means {@code TRUE}),
375+ * preserving backwards-compatible behavior of always writing type id.
376+ *
377+ * @since 2.22
378+ */
379+ public OptBoolean writeTypeIdForDefaultImpl () default OptBoolean .DEFAULT ;
380+
381+ /*
382+ /**********************************************************************
383+ /* Helper classes
384+ /**********************************************************************
385+ */
386+
387+ /**
388+ * This marker class that is only to be used with <code>defaultImpl</code>
389+ * annotation property, to indicate that there is no default implementation
390+ * specified.
391+ *
392+ * @deprecated Since 2.5, use any Annotation type (such as {@link JsonTypeInfo}),
393+ * if such behavior is needed; this is rarely necessary.
394+ */
395+ @ Deprecated // since 2.5
396+ public abstract static class None {}
397+
377398 /*
378399 /**********************************************************************
379400 /* Value class used to enclose information, allow for
@@ -399,25 +420,49 @@ public static class Value
399420 protected final boolean _idVisible ;
400421 protected final Boolean _requireTypeIdForSubtypes ;
401422
423+ /**
424+ * @since 2.22
425+ */
426+ protected final Boolean _writeTypeIdForDefaultImpl ;
427+
402428 /*
403429 /**********************************************************************
404430 /* Construction
405431 /**********************************************************************
406432 */
407433
434+ /**
435+ * @since 2.22
436+ */
408437 protected Value (Id idType , As inclusionType ,
409- String propertyName , Class <?> defaultImpl , boolean idVisible , Boolean requireTypeIdForSubtypes )
438+ String propertyName , Class <?> defaultImpl , boolean idVisible ,
439+ Boolean requireTypeIdForSubtypes , Boolean writeTypeIdForDefaultImpl )
410440 {
411441 _defaultImpl = defaultImpl ;
412442 _idType = idType ;
413443 _inclusionType = inclusionType ;
414444 _propertyName = propertyName ;
415445 _idVisible = idVisible ;
416446 _requireTypeIdForSubtypes = requireTypeIdForSubtypes ;
447+ _writeTypeIdForDefaultImpl = writeTypeIdForDefaultImpl ;
417448 }
418449
419- public static Value construct (Id idType , As inclusionType ,
450+ /**
451+ * @deprecated Since 2.22 use the 7-argument overload
452+ */
453+ @ Deprecated
454+ protected Value (Id idType , As inclusionType ,
420455 String propertyName , Class <?> defaultImpl , boolean idVisible , Boolean requireTypeIdForSubtypes )
456+ {
457+ this (idType , inclusionType , propertyName , defaultImpl , idVisible , requireTypeIdForSubtypes , null );
458+ }
459+
460+ /**
461+ * @since 2.22
462+ */
463+ public static Value construct (Id idType , As inclusionType ,
464+ String propertyName , Class <?> defaultImpl , boolean idVisible ,
465+ Boolean requireTypeIdForSubtypes , Boolean writeTypeIdForDefaultImpl )
421466 {
422467 // couple of overrides we need to apply here. First: if no propertyName specified,
423468 // use Id-specific property name
@@ -433,15 +478,29 @@ public static Value construct(Id idType, As inclusionType,
433478 if ((defaultImpl == null ) || defaultImpl .isAnnotation ()) {
434479 defaultImpl = null ;
435480 }
436- return new Value (idType , inclusionType , propertyName , defaultImpl , idVisible , requireTypeIdForSubtypes );
481+ return new Value (idType , inclusionType , propertyName , defaultImpl , idVisible ,
482+ requireTypeIdForSubtypes , writeTypeIdForDefaultImpl );
483+ }
484+
485+ /**
486+ * @deprecated Since 2.22 use the 7-argument overload
487+ */
488+ @ Deprecated
489+ public static Value construct (Id idType , As inclusionType ,
490+ String propertyName , Class <?> defaultImpl , boolean idVisible ,
491+ Boolean requireTypeIdForSubtypes )
492+ {
493+ return construct (idType , inclusionType , propertyName , defaultImpl , idVisible , requireTypeIdForSubtypes , null );
437494 }
438495
439496 public static Value from (JsonTypeInfo src ) {
440497 if (src == null ) {
441498 return null ;
442499 }
443500 return construct (src .use (), src .include (),
444- src .property (), src .defaultImpl (), src .visible (), src .requireTypeIdForSubtypes ().asBoolean ());
501+ src .property (), src .defaultImpl (), src .visible (),
502+ src .requireTypeIdForSubtypes ().asBoolean (),
503+ src .writeTypeIdForDefaultImpl ().asBoolean ());
445504 }
446505
447506 /*
@@ -452,32 +511,47 @@ public static Value from(JsonTypeInfo src) {
452511
453512 public Value withDefaultImpl (Class <?> impl ) {
454513 return (impl == _defaultImpl ) ? this :
455- new Value (_idType , _inclusionType , _propertyName , impl , _idVisible , _requireTypeIdForSubtypes );
514+ new Value (_idType , _inclusionType , _propertyName , impl , _idVisible ,
515+ _requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
456516 }
457517
458518 public Value withIdType (Id idType ) {
459519 return (idType == _idType ) ? this :
460- new Value (idType , _inclusionType , _propertyName , _defaultImpl , _idVisible , _requireTypeIdForSubtypes );
520+ new Value (idType , _inclusionType , _propertyName , _defaultImpl , _idVisible ,
521+ _requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
461522 }
462523
463524 public Value withInclusionType (As inclusionType ) {
464525 return (inclusionType == _inclusionType ) ? this :
465- new Value (_idType , inclusionType , _propertyName , _defaultImpl , _idVisible , _requireTypeIdForSubtypes );
526+ new Value (_idType , inclusionType , _propertyName , _defaultImpl , _idVisible ,
527+ _requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
466528 }
467529
468530 public Value withPropertyName (String propName ) {
469531 return (propName == _propertyName ) ? this :
470- new Value (_idType , _inclusionType , propName , _defaultImpl , _idVisible , _requireTypeIdForSubtypes );
532+ new Value (_idType , _inclusionType , propName , _defaultImpl , _idVisible ,
533+ _requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
471534 }
472535
473536 public Value withIdVisible (boolean visible ) {
474537 return (visible == _idVisible ) ? this :
475- new Value (_idType , _inclusionType , _propertyName , _defaultImpl , visible , _requireTypeIdForSubtypes );
538+ new Value (_idType , _inclusionType , _propertyName , _defaultImpl , visible ,
539+ _requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
476540 }
477-
541+
478542 public Value withRequireTypeIdForSubtypes (Boolean requireTypeIdForSubtypes ) {
479543 return (_requireTypeIdForSubtypes == requireTypeIdForSubtypes ) ? this :
480- new Value (_idType , _inclusionType , _propertyName , _defaultImpl , _idVisible , requireTypeIdForSubtypes );
544+ new Value (_idType , _inclusionType , _propertyName , _defaultImpl , _idVisible ,
545+ requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
546+ }
547+
548+ /**
549+ * @since 2.22
550+ */
551+ public Value withWriteTypeIdForDefaultImpl (Boolean writeTypeIdForDefaultImpl ) {
552+ return (_writeTypeIdForDefaultImpl == writeTypeIdForDefaultImpl ) ? this :
553+ new Value (_idType , _inclusionType , _propertyName , _defaultImpl , _idVisible ,
554+ _requireTypeIdForSubtypes , writeTypeIdForDefaultImpl );
481555 }
482556
483557 /*
@@ -498,6 +572,18 @@ public Class<JsonTypeInfo> valueFor() {
498572 public boolean getIdVisible () { return _idVisible ; }
499573 public Boolean getRequireTypeIdForSubtypes () { return _requireTypeIdForSubtypes ; }
500574
575+ /**
576+ * @since 2.22
577+ */
578+ public Boolean getWriteTypeIdForDefaultImpl () { return _writeTypeIdForDefaultImpl ; }
579+
580+ /**
581+ * @since 2.22
582+ */
583+ public boolean shouldWriteTypeIdForDefaultImpl () {
584+ return (_writeTypeIdForDefaultImpl == null ) || _writeTypeIdForDefaultImpl .booleanValue ();
585+ }
586+
501587 /**
502588 * Static helper method for simple(r) checking of whether there's a Value instance
503589 * that indicates that polymorphic handling is (to be) enabled.
@@ -516,11 +602,11 @@ public static boolean isEnabled(JsonTypeInfo.Value v) {
516602
517603 @ Override
518604 public String toString () {
519- return String .format ("JsonTypeInfo.Value(idType=%s,includeAs=%s,propertyName=%s,defaultImpl=%s,idVisible=%s"
520- + ",requireTypeIdForSubtypes=%s)" ,
605+ return String .format ("JsonTypeInfo.Value(idType=%s,includeAs=%s,propertyName=%s,defaultImpl=%s,idVisible=%s"
606+ + ",requireTypeIdForSubtypes=%s,writeTypeIdForDefaultImpl=%s )" ,
521607 _idType , _inclusionType , _propertyName ,
522608 ((_defaultImpl == null ) ? "NULL" : _defaultImpl .getName ()),
523- _idVisible , _requireTypeIdForSubtypes );
609+ _idVisible , _requireTypeIdForSubtypes , _writeTypeIdForDefaultImpl );
524610 }
525611
526612 @ Override
@@ -530,8 +616,9 @@ public int hashCode() {
530616 hashCode = 31 * hashCode + (_inclusionType != null ? _inclusionType .hashCode () : 0 );
531617 hashCode = 31 * hashCode + (_propertyName != null ? _propertyName .hashCode () : 0 );
532618 hashCode = 31 * hashCode + (_defaultImpl != null ? _defaultImpl .hashCode () : 0 );
533- hashCode = 31 * hashCode + (_requireTypeIdForSubtypes ? 11 : - 17 );
619+ hashCode = 31 * hashCode + Objects . hashCode (_requireTypeIdForSubtypes );
534620 hashCode = 31 * hashCode + (_idVisible ? 11 : -17 );
621+ hashCode = 31 * hashCode + Objects .hashCode (_writeTypeIdForDefaultImpl );
535622 return hashCode ;
536623 }
537624
@@ -551,6 +638,7 @@ private static boolean _equals(Value a, Value b)
551638 && (a ._idVisible == b ._idVisible )
552639 && Objects .equals (a ._propertyName , b ._propertyName )
553640 && Objects .equals (a ._requireTypeIdForSubtypes , b ._requireTypeIdForSubtypes )
641+ && Objects .equals (a ._writeTypeIdForDefaultImpl , b ._writeTypeIdForDefaultImpl )
554642 ;
555643 }
556644 }
0 commit comments