@@ -33,35 +33,194 @@ public void setEnforce32BitInt(boolean enforce32BitInt) {
33
33
34
34
public Object convertToJSONPrimitive (String text ) {
35
35
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
+ }
47
53
}
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 ()) {
49
73
primitive = text ;
50
74
}
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
+ }
66
225
}
67
226
}
0 commit comments