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+ * Value that indicates the default radix(numeric base) to use for outputting {@link java.lang.Number} properties
85+ * when {@link Shape#STRING} is specified.
86+ */
87+ public final static byte DEFAULT_RADIX = 10 ;
88+
8189 /**
8290 * Datatype-specific additional piece of configuration that may be used
8391 * to further refine formatting aspects. This may, for example, determine
126134 */
127135 public OptBoolean lenient () default OptBoolean .DEFAULT ;
128136
137+ /**
138+ * Property that indicates the numeric base used to output {@link java.lang.Number} properties when {@link Shape#STRING}
139+ * is specified.
140+ * For example, if 2 is used, then the output will be a binary representation of a number as a string,
141+ * and with 16, the number will be outputted in the hexadecimal form.
142+ *
143+ * @since 2.21
144+ */
145+ public byte radix () default DEFAULT_RADIX ;
146+
129147 /**
130148 * Set of {@link JsonFormat.Feature}s to explicitly enable with respect
131149 * to handling of annotated property. This will have precedence over possible
@@ -518,21 +536,41 @@ public static class Value
518536 */
519537 private final Features _features ;
520538
539+ /**
540+ * @since 2.21
541+ */
542+ private final byte _radix ;
543+
521544 // lazily constructed when created from annotations
522545 private transient TimeZone _timezone ;
523546
524547 public Value () {
525- this ("" , Shape .ANY , "" , "" , Features .empty (), null );
548+ this ("" , Shape .ANY , "" , "" , Features .empty (), null , DEFAULT_RADIX );
526549 }
527550
528551 public Value (JsonFormat ann ) {
529552 this (ann .pattern (), ann .shape (), ann .locale (), ann .timezone (),
530- Features .construct (ann ), ann .lenient ().asBoolean ());
553+ Features .construct (ann ), ann .lenient ().asBoolean (), ann .radix ());
554+ }
555+
556+ /**
557+ * @since 2.21
558+ */
559+ public Value (String p , Shape sh , String localeStr , String tzStr , Features f ,
560+ Boolean lenient , byte radix )
561+ {
562+ this (p , sh ,
563+ (localeStr == null || localeStr .length () == 0 || DEFAULT_LOCALE .equals (localeStr )) ?
564+ null : new Locale (localeStr ),
565+ (tzStr == null || tzStr .length () == 0 || DEFAULT_TIMEZONE .equals (tzStr )) ?
566+ null : tzStr ,
567+ null , f , lenient , radix );
531568 }
532569
533570 /**
534571 * @since 2.9
535572 */
573+ @ Deprecated //since 2.21
536574 public Value (String p , Shape sh , String localeStr , String tzStr , Features f ,
537575 Boolean lenient )
538576 {
@@ -544,9 +582,26 @@ public Value(String p, Shape sh, String localeStr, String tzStr, Features f,
544582 null , f , lenient );
545583 }
546584
585+ /**
586+ * @since 2.21
587+ */
588+ public Value (String p , Shape sh , Locale l , TimeZone tz , Features f ,
589+ Boolean lenient , byte radix )
590+ {
591+ _pattern = (p == null ) ? "" : p ;
592+ _shape = (sh == null ) ? Shape .ANY : sh ;
593+ _locale = l ;
594+ _timezone = tz ;
595+ _timezoneStr = null ;
596+ _features = (f == null ) ? Features .empty () : f ;
597+ _lenient = lenient ;
598+ _radix = radix ;
599+ }
600+
547601 /**
548602 * @since 2.9
549603 */
604+ @ Deprecated //since 2.21
550605 public Value (String p , Shape sh , Locale l , TimeZone tz , Features f ,
551606 Boolean lenient )
552607 {
@@ -557,13 +612,14 @@ public Value(String p, Shape sh, Locale l, TimeZone tz, Features f,
557612 _timezoneStr = null ;
558613 _features = (f == null ) ? Features .empty () : f ;
559614 _lenient = lenient ;
615+ _radix = DEFAULT_RADIX ;
560616 }
561617
562618 /**
563- * @since 2.9
619+ * @since 2.21
564620 */
565621 public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f ,
566- Boolean lenient )
622+ Boolean lenient , byte radix )
567623 {
568624 _pattern = (p == null ) ? "" : p ;
569625 _shape = (sh == null ) ? Shape .ANY : sh ;
@@ -572,6 +628,17 @@ public Value(String p, Shape sh, Locale l, String tzStr, TimeZone tz, Features f
572628 _timezoneStr = tzStr ;
573629 _features = (f == null ) ? Features .empty () : f ;
574630 _lenient = lenient ;
631+ _radix = radix ;
632+ }
633+
634+ /**
635+ * @since 2.9
636+ */
637+ @ Deprecated //since 2.21
638+ public Value (String p , Shape sh , Locale l , String tzStr , TimeZone tz , Features f ,
639+ Boolean lenient )
640+ {
641+ this (p , sh , l , tzStr , tz , f , lenient , DEFAULT_RADIX );
575642 }
576643
577644 /**
@@ -662,37 +729,45 @@ public final Value withOverrides(Value overrides) {
662729 } else {
663730 tz = overrides ._timezone ;
664731 }
665- return new Value (p , sh , l , tzStr , tz , f , lenient );
732+ return new Value (p , sh , l , tzStr , tz , f , lenient , overrides . _radix );
666733 }
667734
668735 /**
669736 * @since 2.6
670737 */
671738 public static Value forPattern (String p ) {
672- return new Value (p , null , null , null , null , Features .empty (), null );
739+ return new Value (p , null , null , null , null , Features .empty (), null , DEFAULT_RADIX );
673740 }
674741
675742 /**
676743 * @since 2.7
677744 */
678745 public static Value forShape (Shape sh ) {
679- return new Value ("" , sh , null , null , null , Features .empty (), null );
746+ return new Value ("" , sh , null , null , null , Features .empty (), null , DEFAULT_RADIX );
680747 }
681748
682749 /**
683750 * @since 2.9
684751 */
685752 public static Value forLeniency (boolean lenient ) {
686753 return new Value ("" , null , null , null , null , Features .empty (),
687- Boolean .valueOf (lenient ));
754+ Boolean .valueOf (lenient ), DEFAULT_RADIX );
755+ }
756+
757+ /**
758+ * @since 2.21
759+ */
760+ public static Value forRadix (byte radix ) {
761+ return new Value ("" , null , null , null , null , Features .empty (),
762+ null , radix );
688763 }
689764
690765 /**
691766 * @since 2.1
692767 */
693768 public Value withPattern (String p ) {
694769 return new Value (p , _shape , _locale , _timezoneStr , _timezone ,
695- _features , _lenient );
770+ _features , _lenient , _radix );
696771 }
697772
698773 /**
@@ -703,15 +778,15 @@ public Value withShape(Shape s) {
703778 return this ;
704779 }
705780 return new Value (_pattern , s , _locale , _timezoneStr , _timezone ,
706- _features , _lenient );
781+ _features , _lenient , _radix );
707782 }
708783
709784 /**
710785 * @since 2.1
711786 */
712787 public Value withLocale (Locale l ) {
713788 return new Value (_pattern , _shape , l , _timezoneStr , _timezone ,
714- _features , _lenient );
789+ _features , _lenient , _radix );
715790 }
716791
717792 /**
@@ -730,7 +805,18 @@ public Value withLenient(Boolean lenient) {
730805 return this ;
731806 }
732807 return new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
733- _features , lenient );
808+ _features , lenient , _radix );
809+ }
810+
811+ /**
812+ * @since 2.21
813+ */
814+ public Value withRadix (byte radix ) {
815+ if (radix == _radix ) {
816+ return this ;
817+ }
818+ return new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
819+ _features , _lenient , radix );
734820 }
735821
736822 /**
@@ -740,7 +826,7 @@ public Value withFeature(JsonFormat.Feature f) {
740826 Features newFeats = _features .with (f );
741827 return (newFeats == _features ) ? this :
742828 new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
743- newFeats , _lenient );
829+ newFeats , _lenient , _radix );
744830 }
745831
746832 /**
@@ -750,7 +836,7 @@ public Value withoutFeature(JsonFormat.Feature f) {
750836 Features newFeats = _features .without (f );
751837 return (newFeats == _features ) ? this :
752838 new Value (_pattern , _shape , _locale , _timezoneStr , _timezone ,
753- newFeats , _lenient );
839+ newFeats , _lenient , _radix );
754840 }
755841
756842 @ Override
@@ -773,6 +859,11 @@ public Boolean getLenient() {
773859 return _lenient ;
774860 }
775861
862+ /**
863+ * @since 2.21
864+ */
865+ public byte getRadix () { return _radix ; }
866+
776867 /**
777868 * Convenience method equivalent to
778869 *<pre>
@@ -848,6 +939,15 @@ public boolean hasLenient() {
848939 return _lenient != null ;
849940 }
850941
942+ /**
943+ * Accessor for checking whether non-default (non-10) radix has been specified.
944+ *
945+ * @since 2.21
946+ */
947+ public boolean hasNonDefaultRadix () {
948+ return _radix != DEFAULT_RADIX ;
949+ }
950+
851951 /**
852952 * Accessor for checking whether this format value has specific setting for
853953 * given feature. Result is 3-valued with either `null`, {@link Boolean#TRUE} or
@@ -872,8 +972,8 @@ public Features getFeatures() {
872972
873973 @ Override
874974 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 );
975+ return String .format ("JsonFormat.Value(pattern=%s,shape=%s,lenient=%s,locale=%s,timezone=%s,features=%s,radix=%s )" ,
976+ _pattern , _shape , _lenient , _locale , _timezoneStr , _features , _radix );
877977 }
878978
879979 @ Override
@@ -908,7 +1008,8 @@ public boolean equals(Object o) {
9081008 && Objects .equals (_timezoneStr , other ._timezoneStr )
9091009 && Objects .equals (_pattern , other ._pattern )
9101010 && Objects .equals (_timezone , other ._timezone )
911- && Objects .equals (_locale , other ._locale );
1011+ && Objects .equals (_locale , other ._locale )
1012+ && Objects .equals (_radix , other ._radix );
9121013 }
9131014 }
9141015}
0 commit comments