2424import java .util .Locale ;
2525import java .util .Map ;
2626import java .util .concurrent .atomic .AtomicInteger ;
27+ import java .util .regex .Pattern ;
2728
2829import org .json .CDL ;
2930import org .json .JSONArray ;
6061 * otherwise be impossible.
6162 */
6263public class JSONObjectTest {
63-
64+
65+ /**
66+ * Regular Expression Pattern that matches JSON Numbers. This is primarily used for
67+ * output to guarantee that we are always writing valid JSON.
68+ */
69+ static final Pattern NUMBER_PATTERN = Pattern .compile ("-?(?:0|[1-9]\\ d*)(?:\\ .\\ d+)?(?:[eE][+-]?\\ d+)?" );
70+
6471 /**
6572 * Tests that the similar method is working as expected.
6673 */
@@ -87,6 +94,67 @@ public void verifySimilar() {
8794 assertTrue ("Should eval to true" , obj1 .similar (obj3 ));
8895
8996 }
97+
98+ @ Test
99+ public void timeNumberParsing () {
100+ // test data to use
101+ final String [] testData = new String [] {
102+ null ,
103+ "" ,
104+ "100" ,
105+ "-100" ,
106+ "abc123" ,
107+ "012345" ,
108+ "100.5e199" ,
109+ "-100.5e199" ,
110+ "DEADBEEF" ,
111+ "0xDEADBEEF" ,
112+ "1234567890.1234567890" ,
113+ "-1234567890.1234567890" ,
114+ "adloghakuidghauiehgauioehgdkjfb nsruoh aeu noerty384 nkljfgh "
115+ + "395h tdfn kdz8yt3 4hkls gn.ey85 4hzfhnz.o8y5a84 onvklt "
116+ + "yh389thub nkz8y49lihv al4itlaithknty8hnbl"
117+ // long (in length) number sequences with invalid data at the end of the
118+ // string offer very poor performance for the REGEX.
119+ ,"123467890123467890123467890123467890123467890123467890123467"
120+ + "8901234678901234678901234678901234678901234678901234678"
121+ + "9012346789012346789012346789012346789012346789012346789"
122+ + "0a"
123+ };
124+ final int testDataLength = testData .length ;
125+ final int iterations = 1000000 ;
126+
127+ // 10 million iterations 1,000,000 * 10
128+ long startTime = System .nanoTime ();
129+ for (int i = 0 ; i < iterations ; i ++) {
130+ for (int j = 0 ; j < testDataLength ; j ++) {
131+ try {
132+ BigDecimal v1 = new BigDecimal (testData [j ]);
133+ v1 .signum ();
134+ } catch (Exception ignore ) {
135+ //do nothing
136+ }
137+ }
138+ }
139+ final long elapsedNano1 = System .nanoTime () - startTime ;
140+ System .out .println ("new BigDecimal(testData[]) : " + elapsedNano1 / 1000000 + " ms" );
141+
142+ startTime = System .nanoTime ();
143+ for (int i = 0 ; i < iterations ; i ++) {
144+ for (int j = 0 ; j < testDataLength ; j ++) {
145+ try {
146+ boolean v2 = NUMBER_PATTERN .matcher (testData [j ]).matches ();
147+ assert v2 == !!v2 ;
148+ } catch (Exception ignore ) {
149+ //do nothing
150+ }
151+ }
152+ }
153+ final long elapsedNano2 = System .nanoTime () - startTime ;
154+ System .out .println ("NUMBER_PATTERN.matcher(testData[]).matches() : " + elapsedNano2 / 1000000 + " ms" );
155+ // don't assert normally as the testing is machine dependent.
156+ // assertTrue("Expected Pattern matching to be faster than BigDecimal constructor",elapsedNano2<elapsedNano1);
157+ }
90158
91159 /**
92160 * JSONObject built from a bean, but only using a null value.
@@ -736,14 +804,18 @@ public void jsonObjectValues() {
736804 jsonObject .optDouble ("doubleKey" ) == -23.45e7 );
737805 assertTrue ("opt doubleKey with Default should be double" ,
738806 jsonObject .optDouble ("doubleStrKey" , Double .NaN ) == 1 );
739- assertTrue ("opt negZeroKey should be double " ,
740- Double . compare ( jsonObject .optDouble ("negZeroKey" ), - 0.0d ) == 0 );
741- assertTrue ("opt negZeroStrKey with Default should be double " ,
742- Double . compare ( jsonObject .optDouble ( "negZeroStrKey" ), - 0.0d ) == 0 );
807+ assertTrue ("opt negZeroKey should be a Double " ,
808+ jsonObject .opt ("negZeroKey" ) instanceof Double );
809+ assertTrue ("get negZeroKey should be a Double " ,
810+ jsonObject .get ( "negZeroKey" ) instanceof Double );
743811 assertTrue ("optNumber negZeroKey should return Double" ,
744812 jsonObject .optNumber ("negZeroKey" ) instanceof Double );
745813 assertTrue ("optNumber negZeroStrKey should return Double" ,
746814 jsonObject .optNumber ("negZeroStrKey" ) instanceof Double );
815+ assertTrue ("opt negZeroKey should be double" ,
816+ Double .compare (jsonObject .optDouble ("negZeroKey" ), -0.0d ) == 0 );
817+ assertTrue ("opt negZeroStrKey with Default should be double" ,
818+ Double .compare (jsonObject .optDouble ("negZeroStrKey" ), -0.0d ) == 0 );
747819 assertTrue ("optNumber negZeroKey should be -0.0" ,
748820 Double .compare (jsonObject .optNumber ("negZeroKey" ).doubleValue (), -0.0d ) == 0 );
749821 assertTrue ("optNumber negZeroStrKey should be -0.0" ,
@@ -1138,6 +1210,10 @@ public void bigNumberOperations() {
11381210 jsonObject .optBigInteger ("bigInt" , BigInteger .ONE ).equals (bigInteger ));
11391211 assertTrue ("jsonObject serializes bigInt correctly" ,
11401212 jsonObject .toString ().equals ("{\" bigInt\" :123456789012345678901234567890}" ));
1213+ assertTrue ("BigInteger as BigDecimal" ,
1214+ jsonObject .getBigDecimal ("bigInt" ).equals (new BigDecimal (bigInteger )));
1215+
1216+
11411217 jsonObject = new JSONObject ();
11421218 jsonObject .put ("bigDec" , bigDecimal );
11431219 assertTrue ("jsonObject.put() handles bigDec correctly" ,
@@ -1150,19 +1226,18 @@ public void bigNumberOperations() {
11501226 jsonObject .toString ().equals (
11511227 "{\" bigDec\" :123456789012345678901234567890.12345678901234567890123456789}" ));
11521228
1229+ assertTrue ("BigDecimal as BigInteger" ,
1230+ jsonObject .getBigInteger ("bigDec" ).equals (bigDecimal .toBigInteger ()));
11531231 /**
11541232 * exercise some exceptions
11551233 */
11561234 try {
1235+ // bigInt key does not exist
11571236 jsonObject .getBigDecimal ("bigInt" );
11581237 fail ("expected an exeption" );
11591238 } catch (JSONException ignored ) {}
11601239 obj = jsonObject .optBigDecimal ("bigInt" , BigDecimal .ONE );
11611240 assertTrue ("expected BigDecimal" , obj .equals (BigDecimal .ONE ));
1162- try {
1163- jsonObject .getBigInteger ("bigDec" );
1164- fail ("expected an exeption" );
1165- } catch (JSONException ignored ) {}
11661241 jsonObject .put ("stringKey" , "abc" );
11671242 try {
11681243 jsonObject .getBigDecimal ("stringKey" );
@@ -2392,6 +2467,8 @@ public void jsonObjectOptBigDecimal() {
23922467 assertEquals (new BigDecimal ("1234" ),jo .optBigDecimal ("bigInteger" , null ));
23932468 assertEquals (new BigDecimal ("1234.56789" ),jo .optBigDecimal ("bigDecimal" , null ));
23942469 assertNull (jo .optBigDecimal ("nullVal" , null ));
2470+ assertEquals (jo .optBigDecimal ("float" , null ),jo .getBigDecimal ("float" ));
2471+ assertEquals (jo .optBigDecimal ("double" , null ),jo .getBigDecimal ("double" ));
23952472 }
23962473
23972474 /**
0 commit comments