@@ -33,35 +33,194 @@ public void setEnforce32BitInt(boolean enforce32BitInt) {
3333
3434 public Object convertToJSONPrimitive (String text ) {
3535 if (text == null ) return text ;
36- Object primitive = null ;
37- // Attempt to convert to Integer
38- try {
39- primitive = enforce32BitInt ? Integer .valueOf (text ) : Long .valueOf (text );
40- } catch (Exception e ) {/**/ }
41- // Attempt to convert to double
42- if (primitive == null ) {
43- try {
44- Double v = Double .valueOf (text );
45- if ( !v .isInfinite () && !v .isNaN () ) {
46- primitive = v ;
36+
37+ // If there's at least one character
38+ if (text .length () >= 1 ) {
39+ // find the first character
40+ char first = text .charAt (0 );
41+
42+ // Is it incompatible with a number?
43+ if ((first < '0' || first > '9' ) && first != '-' ) {
44+ // Yes it is, so special case check for Boolean values
45+ if (first == 't' ) {
46+ if (text .equals ("true" )) {
47+ return Boolean .TRUE ;
48+ }
49+ } else if (first == 'f' ) {
50+ if (text .equals ("false" )) {
51+ return Boolean .FALSE ;
52+ }
4753 }
48- else {
54+
55+ // Definitely not a Boolean or a number, so return the original value
56+ return text ;
57+ }
58+ }
59+
60+ Object primitive = null ;
61+
62+ if (enforce32BitInt ) {
63+ primitive = getInteger (text );
64+ } else {
65+ primitive = getLong (text );
66+ }
67+
68+ if (primitive == null ) {
69+ Double dbl = getDouble (text );
70+
71+ if (dbl != null ) {
72+ if (dbl .isInfinite () || dbl .isNaN ()) {
4973 primitive = text ;
5074 }
51- } catch (Exception e ) {/**/ }
52- }
53- // Attempt to convert to boolean
54- if (primitive == null ) {
55- if (text .trim ().equalsIgnoreCase ("true" ) || text .trim ().equalsIgnoreCase ("false" )) {
56- primitive = Boolean .valueOf (text );
57- }
58- }
59-
60- if (primitive == null || !primitive .toString ().equals (text )) {
61- // Default String
62- primitive = text ;
63- }
64-
65- return primitive ;
75+ else {
76+ primitive = dbl ;
77+ }
78+ }
79+ }
80+
81+ if (primitive == null || !primitive .toString ().equals (text )) {
82+ // Default String
83+ primitive = text ;
84+ }
85+
86+ return primitive ;
87+ }
88+
89+ private static final int MAX_LENGTH_LONG = String .valueOf (Long .MAX_VALUE ).length ();
90+ private static final int MAX_LENGTH_LONG_NEGATIVE = String .valueOf (Long .MAX_VALUE ).length () + 1 ;
91+
92+ /**
93+ * Try to get a Long value efficiently, avoiding Exceptions
94+ */
95+ private static Long getLong (String text )
96+ {
97+ // handle an empty string
98+ if (text .isEmpty ()) return null ;
99+
100+ // if the text is too long it can't be a Long
101+ if (text .charAt (0 ) == '-' ) {
102+ if (text .length () > MAX_LENGTH_LONG_NEGATIVE ) {
103+ return null ;
104+ }
105+ } else if (text .length () > MAX_LENGTH_LONG ) {
106+ return null ;
107+ }
108+
109+ // Handle a leading minus sign
110+ int i = 0 ;
111+ if (text .charAt (0 ) == '-' ) {
112+ if (text .length () > 1 ) {
113+ i ++;
114+ } else {
115+ return null ;
116+ }
117+ }
118+
119+ // Check each character is a digit
120+ for (; i < text .length (); i ++) {
121+ if (!Character .isDigit (text .charAt (i ))) {
122+ return null ;
123+ }
124+ }
125+
126+ // It looks like it might be a Long, so give it a go
127+ try {
128+ return Long .parseLong (text );
129+ } catch (Exception e ) {
130+ // It isn't a Long
131+ return null ;
132+ }
133+ }
134+
135+ private static final int MAX_LENGTH_INTEGER = String .valueOf (Integer .MAX_VALUE ).length ();
136+ private static final int MAX_LENGTH_INTEGER_NEGATIVE = String .valueOf (Integer .MAX_VALUE ).length () + 1 ;
137+
138+ /**
139+ * Try to get an Integer value efficiently, avoiding Exceptions
140+ */
141+ private static Integer getInteger (String text ) {
142+ // handle an empty string
143+ if (text .isEmpty ()) return null ;
144+
145+ // if the text is too long it can't be an Integer
146+ if (text .charAt (0 ) == '-' ) {
147+ if (text .length () > MAX_LENGTH_INTEGER_NEGATIVE ) {
148+ return null ;
149+ }
150+ }
151+ else if (text .length () > MAX_LENGTH_INTEGER ) {
152+ return null ;
153+ }
154+
155+ // Handle a leading minus sign
156+ int i = 0 ;
157+ if (text .charAt (0 ) == '-' ) {
158+ if (text .length () > 1 ) {
159+ i ++;
160+ } else {
161+ return null ;
162+ }
163+ }
164+
165+ // Check each character is a digit
166+ for (; i < text .length (); i ++) {
167+ if (!Character .isDigit (text .charAt (i ))) {
168+ return null ;
169+ }
170+ }
171+
172+ // It looks like it might be an Integer, so give it a go
173+ try {
174+ return Integer .parseInt (text );
175+ } catch (Exception e ) {
176+ // It isn't an Integer
177+ return null ;
178+ }
179+ }
180+
181+ /**
182+ * Try to get a Double value efficiently, avoiding Exceptions
183+ */
184+ private static Double getDouble (String text ) {
185+ boolean foundDP = false ;
186+ boolean foundExp = false ;
187+
188+ // handle an empty string
189+ if (text .isEmpty ())
190+ return null ;
191+
192+ // Handle a leading minus sign
193+ int i = 0 ;
194+ if (text .charAt (0 ) == '-' ) {
195+ if (text .length () > 1 )
196+ i ++;
197+ else
198+ return null ;
199+ }
200+
201+ // Check each character is a digit
202+ for (; i < text .length (); i ++) {
203+ char next = text .charAt (i );
204+ if (!Character .isDigit (next )) {
205+ if (next == '.' ) {
206+ if (foundDP )
207+ return null ;
208+ foundDP = true ;
209+ } else if (next == 'E' || next == 'e' ) {
210+ if (foundExp )
211+ return null ;
212+ foundExp = true ;
213+ } else
214+ return null ;
215+ }
216+ }
217+
218+ // It looks like it might be a Double, so give it a go
219+ try {
220+ return Double .parseDouble (text );
221+ } catch (Exception e ) {
222+ // It isn't a Double
223+ return null ;
224+ }
66225 }
67226}
0 commit comments