@@ -244,7 +244,50 @@ public double getDouble(int index) throws JSONException {
244244 return object instanceof Number ? ((Number ) object ).doubleValue ()
245245 : Double .parseDouble ((String ) object );
246246 } catch (Exception e ) {
247- throw new JSONException ("JSONArray[" + index + "] is not a number." );
247+ throw new JSONException ("JSONArray[" + index + "] is not a number." , e );
248+ }
249+ }
250+
251+ /**
252+ * Get the float value associated with a key.
253+ *
254+ * @param index
255+ * The index must be between 0 and length() - 1.
256+ * @return The numeric value.
257+ * @throws JSONException
258+ * if the key is not found or if the value is not a Number
259+ * object and cannot be converted to a number.
260+ */
261+ public float getFloat (int index ) throws JSONException {
262+ Object object = this .get (index );
263+ try {
264+ return object instanceof Number ? ((Number ) object ).floatValue ()
265+ : Float .parseFloat (object .toString ());
266+ } catch (Exception e ) {
267+ throw new JSONException ("JSONArray[" + index
268+ + "] is not a number." , e );
269+ }
270+ }
271+
272+ /**
273+ * Get the Number value associated with a key.
274+ *
275+ * @param index
276+ * The index must be between 0 and length() - 1.
277+ * @return The numeric value.
278+ * @throws JSONException
279+ * if the key is not found or if the value is not a Number
280+ * object and cannot be converted to a number.
281+ */
282+ public Number getNumber (int index ) throws JSONException {
283+ Object object = this .get (index );
284+ try {
285+ if (object instanceof Number ) {
286+ return (Number )object ;
287+ }
288+ return JSONObject .stringToNumber (object .toString ());
289+ } catch (Exception e ) {
290+ throw new JSONException ("JSONArray[" + index + "] is not a number." , e );
248291 }
249292 }
250293
@@ -266,9 +309,8 @@ public <E extends Enum<E>> E getEnum(Class<E> clazz, int index) throws JSONExcep
266309 // JSONException should really take a throwable argument.
267310 // If it did, I would re-implement this with the Enum.valueOf
268311 // method and place any thrown exception in the JSONException
269- throw new JSONException ("JSONObject[" + JSONObject .quote (Integer .toString (index ))
270- + "] is not an enum of type " + JSONObject .quote (clazz .getSimpleName ())
271- + "." );
312+ throw new JSONException ("JSONArray[" + index + "] is not an enum of type "
313+ + JSONObject .quote (clazz .getSimpleName ()) + "." );
272314 }
273315 return val ;
274316 }
@@ -289,7 +331,7 @@ public BigDecimal getBigDecimal (int index) throws JSONException {
289331 return new BigDecimal (object .toString ());
290332 } catch (Exception e ) {
291333 throw new JSONException ("JSONArray[" + index +
292- "] could not convert to BigDecimal." );
334+ "] could not convert to BigDecimal." , e );
293335 }
294336 }
295337
@@ -309,7 +351,7 @@ public BigInteger getBigInteger (int index) throws JSONException {
309351 return new BigInteger (object .toString ());
310352 } catch (Exception e ) {
311353 throw new JSONException ("JSONArray[" + index +
312- "] could not convert to BigInteger." );
354+ "] could not convert to BigInteger." , e );
313355 }
314356 }
315357
@@ -328,7 +370,7 @@ public int getInt(int index) throws JSONException {
328370 return object instanceof Number ? ((Number ) object ).intValue ()
329371 : Integer .parseInt ((String ) object );
330372 } catch (Exception e ) {
331- throw new JSONException ("JSONArray[" + index + "] is not a number." );
373+ throw new JSONException ("JSONArray[" + index + "] is not a number." , e );
332374 }
333375 }
334376
@@ -384,7 +426,7 @@ public long getLong(int index) throws JSONException {
384426 return object instanceof Number ? ((Number ) object ).longValue ()
385427 : Long .parseLong ((String ) object );
386428 } catch (Exception e ) {
387- throw new JSONException ("JSONArray[" + index + "] is not a number." );
429+ throw new JSONException ("JSONArray[" + index + "] is not a number." , e );
388430 }
389431 }
390432
@@ -518,11 +560,63 @@ public double optDouble(int index) {
518560 * @return The value.
519561 */
520562 public double optDouble (int index , double defaultValue ) {
521- try {
522- return this .getDouble (index );
523- } catch (Exception e ) {
563+ Object val = this .opt (index );
564+ if (JSONObject .NULL .equals (val )) {
524565 return defaultValue ;
525566 }
567+ if (val instanceof Number ){
568+ return ((Number ) val ).doubleValue ();
569+ }
570+ if (val instanceof String ) {
571+ try {
572+ return Double .parseDouble ((String ) val );
573+ } catch (Exception e ) {
574+ return defaultValue ;
575+ }
576+ }
577+ return defaultValue ;
578+ }
579+
580+ /**
581+ * Get the optional float value associated with an index. NaN is returned
582+ * if there is no value for the index, or if the value is not a number and
583+ * cannot be converted to a number.
584+ *
585+ * @param index
586+ * The index must be between 0 and length() - 1.
587+ * @return The value.
588+ */
589+ public float optFloat (int index ) {
590+ return this .optFloat (index , Float .NaN );
591+ }
592+
593+ /**
594+ * Get the optional float value associated with an index. The defaultValue
595+ * is returned if there is no value for the index, or if the value is not a
596+ * number and cannot be converted to a number.
597+ *
598+ * @param index
599+ * subscript
600+ * @param defaultValue
601+ * The default value.
602+ * @return The value.
603+ */
604+ public float optFloat (int index , float defaultValue ) {
605+ Object val = this .opt (index );
606+ if (JSONObject .NULL .equals (val )) {
607+ return defaultValue ;
608+ }
609+ if (val instanceof Number ){
610+ return ((Number ) val ).floatValue ();
611+ }
612+ if (val instanceof String ) {
613+ try {
614+ return Float .parseFloat ((String ) val );
615+ } catch (Exception e ) {
616+ return defaultValue ;
617+ }
618+ }
619+ return defaultValue ;
526620 }
527621
528622 /**
@@ -550,11 +644,22 @@ public int optInt(int index) {
550644 * @return The value.
551645 */
552646 public int optInt (int index , int defaultValue ) {
553- try {
554- return this .getInt (index );
555- } catch (Exception e ) {
647+ Object val = this .opt (index );
648+ if (JSONObject .NULL .equals (val )) {
556649 return defaultValue ;
557650 }
651+ if (val instanceof Number ){
652+ return ((Number ) val ).intValue ();
653+ }
654+
655+ if (val instanceof String ) {
656+ try {
657+ return new BigDecimal (val .toString ()).intValue ();
658+ } catch (Exception e ) {
659+ return defaultValue ;
660+ }
661+ }
662+ return defaultValue ;
558663 }
559664
560665 /**
@@ -615,8 +720,29 @@ public <E extends Enum<E>> E optEnum(Class<E> clazz, int index, E defaultValue)
615720 * @return The value.
616721 */
617722 public BigInteger optBigInteger (int index , BigInteger defaultValue ) {
723+ Object val = this .opt (index );
724+ if (JSONObject .NULL .equals (val )) {
725+ return defaultValue ;
726+ }
727+ if (val instanceof BigInteger ){
728+ return (BigInteger ) val ;
729+ }
730+ if (val instanceof BigDecimal ){
731+ return ((BigDecimal ) val ).toBigInteger ();
732+ }
733+ if (val instanceof Double || val instanceof Float ){
734+ return new BigDecimal (((Number ) val ).doubleValue ()).toBigInteger ();
735+ }
736+ if (val instanceof Long || val instanceof Integer
737+ || val instanceof Short || val instanceof Byte ){
738+ return BigInteger .valueOf (((Number ) val ).longValue ());
739+ }
618740 try {
619- return this .getBigInteger (index );
741+ final String valStr = val .toString ();
742+ if (JSONObject .isDecimalNotation (valStr )) {
743+ return new BigDecimal (valStr ).toBigInteger ();
744+ }
745+ return new BigInteger (valStr );
620746 } catch (Exception e ) {
621747 return defaultValue ;
622748 }
@@ -634,8 +760,25 @@ public BigInteger optBigInteger(int index, BigInteger defaultValue) {
634760 * @return The value.
635761 */
636762 public BigDecimal optBigDecimal (int index , BigDecimal defaultValue ) {
763+ Object val = this .opt (index );
764+ if (JSONObject .NULL .equals (val )) {
765+ return defaultValue ;
766+ }
767+ if (val instanceof BigDecimal ){
768+ return (BigDecimal ) val ;
769+ }
770+ if (val instanceof BigInteger ){
771+ return new BigDecimal ((BigInteger ) val );
772+ }
773+ if (val instanceof Double || val instanceof Float ){
774+ return new BigDecimal (((Number ) val ).doubleValue ());
775+ }
776+ if (val instanceof Long || val instanceof Integer
777+ || val instanceof Short || val instanceof Byte ){
778+ return new BigDecimal (((Number ) val ).longValue ());
779+ }
637780 try {
638- return this . getBigDecimal ( index );
781+ return new BigDecimal ( val . toString () );
639782 } catch (Exception e ) {
640783 return defaultValue ;
641784 }
@@ -693,17 +836,73 @@ public long optLong(int index) {
693836 * @return The value.
694837 */
695838 public long optLong (int index , long defaultValue ) {
696- try {
697- return this .getLong (index );
698- } catch (Exception e ) {
839+ Object val = this .opt (index );
840+ if (JSONObject .NULL .equals (val )) {
841+ return defaultValue ;
842+ }
843+ if (val instanceof Number ){
844+ return ((Number ) val ).longValue ();
845+ }
846+
847+ if (val instanceof String ) {
848+ try {
849+ return new BigDecimal (val .toString ()).longValue ();
850+ } catch (Exception e ) {
851+ return defaultValue ;
852+ }
853+ }
854+ return defaultValue ;
855+ }
856+
857+ /**
858+ * Get an optional {@link Number} value associated with a key, or <code>null</code>
859+ * if there is no such key or if the value is not a number. If the value is a string,
860+ * an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
861+ * would be used in cases where type coercion of the number value is unwanted.
862+ *
863+ * @param index
864+ * The index must be between 0 and length() - 1.
865+ * @return An object which is the value.
866+ */
867+ public Number optNumber (int index ) {
868+ return this .optNumber (index , null );
869+ }
870+
871+ /**
872+ * Get an optional {@link Number} value associated with a key, or the default if there
873+ * is no such key or if the value is not a number. If the value is a string,
874+ * an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
875+ * would be used in cases where type coercion of the number value is unwanted.
876+ *
877+ * @param index
878+ * The index must be between 0 and length() - 1.
879+ * @param defaultValue
880+ * The default.
881+ * @return An object which is the value.
882+ */
883+ public Number optNumber (int index , Number defaultValue ) {
884+ Object val = this .opt (index );
885+ if (JSONObject .NULL .equals (val )) {
699886 return defaultValue ;
700887 }
888+ if (val instanceof Number ){
889+ return (Number ) val ;
890+ }
891+
892+ if (val instanceof String ) {
893+ try {
894+ return JSONObject .stringToNumber ((String ) val );
895+ } catch (Exception e ) {
896+ return defaultValue ;
897+ }
898+ }
899+ return defaultValue ;
701900 }
702901
703902 /**
704903 * Get the optional string value associated with an index. It returns an
705904 * empty string if there is no value at that index. If the value is not a
706- * string and is not null, then it is coverted to a string.
905+ * string and is not null, then it is converted to a string.
707906 *
708907 * @param index
709908 * The index must be between 0 and length() - 1.
0 commit comments