4646 * This is useful to prevent large numeric values from being rounded to their closest double
4747 * values when deserialized by JSON parsers (for instance <code>JSON.parse()</code> in web
4848 * browsers) that do not support numbers with more than 53 bits of precision.
49+ * When serializing {@link java.lang.Number} to a string, it is possible to specify radix,
50+ * the numeric base used to output the number in.
4951 * <p>
5052 * They can also be serialized to full objects if {@link Shape#OBJECT} is used.
5153 * Otherwise, the default behavior of serializing to a scalar number value will be preferred.
7880 */
7981 public final static String DEFAULT_TIMEZONE = "##default" ;
8082
83+ /**
84+ * This is a marker signaling that a configured default radix should be used, which typically means 10,
85+ * when serializing {@link java.lang.Number} properties with {@link Shape#STRING}.
86+ * @since 2.21
87+ */
88+ public final static int DEFAULT_RADIX = -1 ;
89+
8190 /**
8291 * Datatype-specific additional piece of configuration that may be used
8392 * to further refine formatting aspects. This may, for example, determine
126135 */
127136 public OptBoolean lenient () default OptBoolean .DEFAULT ;
128137
138+ /**
139+ * Property that indicates the numeric base used to output {@link java.lang.Number} properties when {@link Shape#STRING}
140+ * is specified.
141+ * For example, if 2 is used, then the output will be a binary representation of a number as a string,
142+ * and with 16, the number will be outputted in the hexadecimal form.
143+ *
144+ * @since 2.21
145+ */
146+ public int radix () default DEFAULT_RADIX ;
147+
129148 /**
130149 * Set of {@link JsonFormat.Feature}s to explicitly enable with respect
131150 * to handling of annotated property. This will have precedence over possible
@@ -518,21 +537,41 @@ public static class Value
518537 */
519538 private final Features _features ;
520539
540+ /**
541+ * @since 2.21
542+ */
543+ private final int _radix ;
544+
521545 // lazily constructed when created from annotations
522546 private transient TimeZone _timezone ;
523547
524548 public Value () {
525- this ("" , Shape .ANY , "" , "" , Features .empty (), null );
549+ this ("" , Shape .ANY , "" , "" , Features .empty (), null , DEFAULT_RADIX );
526550 }
527551
528552 public Value (JsonFormat ann ) {
529553 this (ann .pattern (), ann .shape (), ann .locale (), ann .timezone (),
530- Features .construct (ann ), ann .lenient ().asBoolean ());
554+ Features .construct (ann ), ann .lenient ().asBoolean (), ann .radix ());
555+ }
556+
557+ /**
558+ * @since 2.21
559+ */
560+ public Value (String p , Shape sh , String localeStr , String tzStr , Features f ,
561+ Boolean lenient , int radix )
562+ {
563+ this (p , sh ,
564+ (localeStr == null || localeStr .length () == 0 || DEFAULT_LOCALE .equals (localeStr )) ?
565+ null : new Locale (localeStr ),
566+ (tzStr == null || tzStr .length () == 0 || DEFAULT_TIMEZONE .equals (tzStr )) ?
567+ null : tzStr ,
568+ null , f , lenient , radix );
531569 }
532570
533571 /**
534572 * @since 2.9
535573 */
574+ @ Deprecated //since 2.21
536575 public Value (String p , Shape sh , String localeStr , String tzStr , Features f ,
537576 Boolean lenient )
538577 {
@@ -544,9 +583,26 @@ public Value(String p, Shape sh, String localeStr, String tzStr, Features f,
544583 null , f , lenient );
545584 }
546585
586+ /**
587+ * @since 2.21
588+ */
589+ public Value (String p , Shape sh , Locale l , TimeZone tz , Features f ,
590+ Boolean lenient , int radix )
591+ {
592+ _pattern = (p == null ) ? "" : p ;
593+ _shape = (sh == null ) ? Shape .ANY : sh ;
594+ _locale = l ;
595+ _timezone = tz ;
596+ _timezoneStr = null ;
597+ _features = (f == null ) ? Features .empty () : f ;
598+ _lenient = lenient ;
599+ _radix = radix ;
600+ }
601+
547602 /**
548603 * @since 2.9
549604 */
605+ @ Deprecated //since 2.21
550606 public Value (String p , Shape sh , Locale l , TimeZone tz , Features f ,
551607 Boolean lenient )
552608 {
@@ -557,13 +613,14 @@ public Value(String p, Shape sh, Locale l, TimeZone tz, Features f,
557613 _timezoneStr = null ;
558614 _features = (f == null ) ? Features .empty () : f ;
559615 _lenient = lenient ;
616+ _radix = DEFAULT_RADIX ;
560617 }
561618
562619 /**
563- * @since 2.9
620+ * @since 2.21
564621 */
565622 public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f ,
566- Boolean lenient )
623+ Boolean lenient , int radix )
567624 {
568625 _pattern = (p == null ) ? "" : p ;
569626 _shape = (sh == null ) ? Shape .ANY : sh ;
@@ -572,6 +629,17 @@ public Value(String p, Shape sh, Locale l, String tzStr, TimeZone tz, Features f
572629 _timezoneStr = tzStr ;
573630 _features = (f == null ) ? Features .empty () : f ;
574631 _lenient = lenient ;
632+ _radix = radix ;
633+ }
634+
635+ /**
636+ * @since 2.9
637+ */
638+ @ Deprecated //since 2.21
639+ public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f ,
640+ Boolean lenient )
641+ {
642+ this (p , sh , l , tzStr , tz , f , lenient , DEFAULT_RADIX );
575643 }
576644
577645 /**
@@ -651,6 +719,10 @@ public final Value withOverrides(Value overrides) {
651719 if (lenient == null ) {
652720 lenient = _lenient ;
653721 }
722+ int radix = overrides ._radix ;
723+ if (radix == DEFAULT_RADIX ) {
724+ radix = _radix ;
725+ }
654726
655727 // timezone not merged, just choose one
656728 String tzStr = overrides ._timezoneStr ;
@@ -662,37 +734,45 @@ public final Value withOverrides(Value overrides) {
662734 } else {
663735 tz = overrides ._timezone ;
664736 }
665- return new Value (p , sh , l , tzStr , tz , f , lenient );
737+ return new Value (p , sh , l , tzStr , tz , f , lenient , radix );
666738 }
667739
668740 /**
669741 * @since 2.6
670742 */
671743 public static Value forPattern (String p ) {
672- return new Value (p , null , null , null , null , Features .empty (), null );
744+ return new Value (p , null , null , null , null , Features .empty (), null , DEFAULT_RADIX );
673745 }
674746
675747 /**
676748 * @since 2.7
677749 */
678750 public static Value forShape (Shape sh ) {
679- return new Value ("" , sh , null , null , null , Features .empty (), null );
751+ return new Value ("" , sh , null , null , null , Features .empty (), null , DEFAULT_RADIX );
680752 }
681753
682754 /**
683755 * @since 2.9
684756 */
685757 public static Value forLeniency (boolean lenient ) {
686758 return new Value ("" , null , null , null , null , Features .empty (),
687- Boolean .valueOf (lenient ));
759+ Boolean .valueOf (lenient ), DEFAULT_RADIX );
760+ }
761+
762+ /**
763+ * @since 2.21
764+ */
765+ public static Value forRadix (int radix ) {
766+ return new Value ("" , null , null , null , null , Features .empty (),
767+ null , radix );
688768 }
689769
690770 /**
691771 * @since 2.1
692772 */
693773 public Value withPattern (String p ) {
694774 return new Value (p , _shape , _locale , _timezoneStr , _timezone ,
695- _features , _lenient );
775+ _features , _lenient , _radix );
696776 }
697777
698778 /**
@@ -703,15 +783,15 @@ public Value withShape(Shape s) {
703783 return this ;
704784 }
705785 return new Value (_pattern , s , _locale , _timezoneStr , _timezone ,
706- _features , _lenient );
786+ _features , _lenient , _radix );
707787 }
708788
709789 /**
710790 * @since 2.1
711791 */
712792 public Value withLocale (Locale l ) {
713793 return new Value (_pattern , _shape , l , _timezoneStr , _timezone ,
714- _features , _lenient );
794+ _features , _lenient , _radix );
715795 }
716796
717797 /**
@@ -730,7 +810,18 @@ public Value withLenient(Boolean lenient) {
730810 return this ;
731811 }
732812 return new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
733- _features , lenient );
813+ _features , lenient , _radix );
814+ }
815+
816+ /**
817+ * @since 2.21
818+ */
819+ public Value withRadix (int radix ) {
820+ if (radix == _radix ) {
821+ return this ;
822+ }
823+ return new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
824+ _features , _lenient , radix );
734825 }
735826
736827 /**
@@ -740,7 +831,7 @@ public Value withFeature(JsonFormat.Feature f) {
740831 Features newFeats = _features .with (f );
741832 return (newFeats == _features ) ? this :
742833 new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
743- newFeats , _lenient );
834+ newFeats , _lenient , _radix );
744835 }
745836
746837 /**
@@ -750,7 +841,7 @@ public Value withoutFeature(JsonFormat.Feature f) {
750841 Features newFeats = _features .without (f );
751842 return (newFeats == _features ) ? this :
752843 new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
753- newFeats , _lenient );
844+ newFeats , _lenient , _radix );
754845 }
755846
756847 @ Override
@@ -773,6 +864,13 @@ public Boolean getLenient() {
773864 return _lenient ;
774865 }
775866
867+ /**
868+ * @return radix to use for serializing subclasses of {@link Number} as strings.
869+ * If set to -1, a custom radix has not been specified.
870+ * @since 2.21
871+ */
872+ public int getRadix () { return _radix ; }
873+
776874 /**
777875 * Convenience method equivalent to
778876 *<pre>
@@ -848,6 +946,15 @@ public boolean hasLenient() {
848946 return _lenient != null ;
849947 }
850948
949+ /**
950+ * Accessor for checking whether non-default radix has been specified.
951+ *
952+ * @since 2.21
953+ */
954+ public boolean hasNonDefaultRadix () {
955+ return _radix != DEFAULT_RADIX ;
956+ }
957+
851958 /**
852959 * Accessor for checking whether this format value has specific setting for
853960 * given feature. Result is 3-valued with either `null`, {@link Boolean#TRUE} or
@@ -872,8 +979,8 @@ public Features getFeatures() {
872979
873980 @ Override
874981 public String toString () {
875- return String .format ("JsonFormat.Value(pattern=%s,shape=%s,lenient=%s,locale=%s,timezone=%s,features=%s)" ,
876- _pattern , _shape , _lenient , _locale , _timezoneStr , _features );
982+ return String .format ("JsonFormat.Value(pattern=%s,shape=%s,lenient=%s,locale=%s,timezone=%s,features=%s,radix=%s )" ,
983+ _pattern , _shape , _lenient , _locale , _timezoneStr , _features , _radix );
877984 }
878985
879986 @ Override
@@ -908,7 +1015,8 @@ public boolean equals(Object o) {
9081015 && Objects .equals (_timezoneStr , other ._timezoneStr )
9091016 && Objects .equals (_pattern , other ._pattern )
9101017 && Objects .equals (_timezone , other ._timezone )
911- && Objects .equals (_locale , other ._locale );
1018+ && Objects .equals (_locale , other ._locale )
1019+ && Objects .equals (_radix , other ._radix );
9121020 }
9131021 }
9141022}
0 commit comments