@@ -171,44 +171,85 @@ public void verifyConstructor() {
171171 */
172172 @ Test
173173 public void verifyNumberOutput (){
174+ /**
175+ * MyNumberContainer is a POJO, so call JSONObject(bean),
176+ * which builds a map of getter names/values
177+ * The only getter is getMyNumber (key=myNumber),
178+ * whose return value is MyNumber. MyNumber extends Number,
179+ * but is not recognized as such by wrap() per current
180+ * implementation, so wrap() returns the default new JSONObject(bean).
181+ * The only getter is getNumber (key=number), whose return value is
182+ * BigDecimal(42).
183+ */
174184 JSONObject jsonObject = new JSONObject (new MyNumberContainer ());
175185 String actual = jsonObject .toString ();
176-
177- // before wrapping of Number is allowed the number was converted as a bean
178186 String expected = "{\" myNumber\" :{\" number\" :42}}" ;
179- //String expected = "{\"myNumber\":42}";
180187 assertEquals ("Not Equal" , expected , actual );
181188
182- // put handles objects differently than the constructor.
189+ /**
190+ * JSONObject.put() handles objects differently than the
191+ * bean constructor. Where the bean ctor wraps objects before
192+ * placing them in the map, put() inserts the object without wrapping.
193+ * In this case, a MyNumber instance is the value.
194+ * The MyNumber.toString() method is responsible for
195+ * returning a reasonable value: the string '42'.
196+ */
183197 jsonObject = new JSONObject ();
184198 jsonObject .put ("myNumber" , new MyNumber ());
185199 actual = jsonObject .toString ();
186- // the output is the toString of the number as a number.
187200 expected = "{\" myNumber\" :42}" ;
188201 assertEquals ("Not Equal" , expected , actual );
189-
202+
203+ /**
204+ * Calls the JSONObject(Map) ctor, which calls wrap() for values.
205+ * AtomicInteger is a Number, but is not recognized by wrap(), per
206+ * current implementation. However, the type is
207+ * 'java.util.concurrent.atomic', so due to the 'java' prefix,
208+ * wrap() inserts the value as a string. That is why 42 comes back
209+ * wrapped in quotes.
210+ */
190211 jsonObject = new JSONObject (Collections .singletonMap ("myNumber" , new AtomicInteger (42 )));
191212 actual = jsonObject .toString ();
192- // before wrapping of Number is allowed the number was converted to a string
193213 expected = "{\" myNumber\" :\" 42\" }" ;
194214 assertEquals ("Not Equal" , expected , actual );
195-
196- // put handles objects differently than the constructor.
215+
216+ /**
217+ * JSONObject.put() inserts the AtomicInteger directly into the
218+ * map not calling wrap(). In toString()->write()->writeValue(),
219+ * AtomicInteger is recognized as a Number, and converted via
220+ * numberToString() into the unquoted string '42'.
221+ */
197222 jsonObject = new JSONObject ();
198223 jsonObject .put ("myNumber" , new AtomicInteger (42 ));
199224 actual = jsonObject .toString ();
200225 expected = "{\" myNumber\" :42}" ;
201226 assertEquals ("Not Equal" , expected , actual );
202-
203- // verify Fraction output
227+
228+ /**
229+ * Calls the JSONObject(Map) ctor, which calls wrap() for values.
230+ * Fraction is a Number, but is not recognized by wrap(), per
231+ * current implementation. As a POJO, Franction is handled as a
232+ * bean and inserted into a contained JSONObject. It has 2 getters,
233+ * for numerator and denominator.
234+ */
204235 jsonObject = new JSONObject (Collections .singletonMap ("myNumber" , new Fraction (4 ,2 )));
236+ assertEquals (1 , jsonObject .length ());
237+ assertEquals (2 , ((JSONObject )(jsonObject .get ("myNumber" ))).length ());
205238 assertEquals ("Numerator" , BigInteger .valueOf (4 ) , jsonObject .query ("/myNumber/numerator" ));
206239 assertEquals ("Denominator" , BigInteger .valueOf (2 ) , jsonObject .query ("/myNumber/denominator" ));
207240
241+ /**
242+ * JSONObject.put() inserts the Fraction directly into the
243+ * map not calling wrap(). In toString()->write()->writeValue(),
244+ * Fraction is recognized as a Number, and converted via
245+ * numberToString() into the unquoted string '4/2'. But the
246+ * BigDecimal sanity check fails, so writeValue() defaults
247+ * to returning a safe JSON quoted string. Pretty slick!
248+ */
208249 jsonObject = new JSONObject ();
209250 jsonObject .put ("myNumber" , new Fraction (4 ,2 ));
210251 actual = jsonObject .toString ();
211- expected = "{\" myNumber\" :4/2}" ; // this is NOT valid JSON!!!!!!!!!!! BUG!
252+ expected = "{\" myNumber\" :\" 4/2\" }" ; // valid JSON, bug fixed
212253 assertEquals ("Not Equal" , expected , actual );
213254 }
214255
@@ -2224,44 +2265,44 @@ public void toMap() {
22242265 "}" ;
22252266
22262267 JSONObject jsonObject = new JSONObject (jsonObjectStr );
2227- Map map = jsonObject .toMap ();
2268+ Map <?,?> map = jsonObject .toMap ();
22282269
22292270 assertTrue ("Map should not be null" , map != null );
22302271 assertTrue ("Map should have 3 elements" , map .size () == 3 );
22312272
2232- List key1List = (List )map .get ("key1" );
2273+ List <?> key1List = (List <?> )map .get ("key1" );
22332274 assertTrue ("key1 should not be null" , key1List != null );
22342275 assertTrue ("key1 list should have 3 elements" , key1List .size () == 3 );
22352276 assertTrue ("key1 value 1 should be 1" , key1List .get (0 ).equals (Integer .valueOf (1 )));
22362277 assertTrue ("key1 value 2 should be 2" , key1List .get (1 ).equals (Integer .valueOf (2 )));
22372278
2238- Map key1Value3Map = (Map )key1List .get (2 );
2279+ Map <?,?> key1Value3Map = (Map <?,?> )key1List .get (2 );
22392280 assertTrue ("Map should not be null" , key1Value3Map != null );
22402281 assertTrue ("Map should have 1 element" , key1Value3Map .size () == 1 );
22412282 assertTrue ("Map key3 should be true" , key1Value3Map .get ("key3" ).equals (Boolean .TRUE ));
22422283
2243- Map key2Map = (Map )map .get ("key2" );
2284+ Map <?,?> key2Map = (Map <?,?> )map .get ("key2" );
22442285 assertTrue ("key2 should not be null" , key2Map != null );
22452286 assertTrue ("key2 map should have 3 elements" , key2Map .size () == 3 );
22462287 assertTrue ("key2 map key 1 should be val1" , key2Map .get ("key1" ).equals ("val1" ));
22472288 assertTrue ("key2 map key 3 should be 42" , key2Map .get ("key3" ).equals (Integer .valueOf (42 )));
22482289
2249- Map key2Val2Map = (Map )key2Map .get ("key2" );
2290+ Map <?,?> key2Val2Map = (Map <?,?> )key2Map .get ("key2" );
22502291 assertTrue ("key2 map key 2 should not be null" , key2Val2Map != null );
22512292 assertTrue ("key2 map key 2 should have an entry" , key2Val2Map .containsKey ("key2" ));
22522293 assertTrue ("key2 map key 2 value should be null" , key2Val2Map .get ("key2" ) == null );
22532294
2254- List key3List = (List )map .get ("key3" );
2295+ List <?> key3List = (List <?> )map .get ("key3" );
22552296 assertTrue ("key3 should not be null" , key3List != null );
22562297 assertTrue ("key3 list should have 3 elements" , key3List .size () == 2 );
22572298
2258- List key3Val1List = (List )key3List .get (0 );
2299+ List <?> key3Val1List = (List <?> )key3List .get (0 );
22592300 assertTrue ("key3 list val 1 should not be null" , key3Val1List != null );
22602301 assertTrue ("key3 list val 1 should have 2 elements" , key3Val1List .size () == 2 );
22612302 assertTrue ("key3 list val 1 list element 1 should be value1" , key3Val1List .get (0 ).equals ("value1" ));
22622303 assertTrue ("key3 list val 1 list element 2 should be 2.1" , key3Val1List .get (1 ).equals (Double .valueOf ("2.1" )));
22632304
2264- List key3Val2List = (List )key3List .get (1 );
2305+ List <?> key3Val2List = (List <?> )key3List .get (1 );
22652306 assertTrue ("key3 list val 2 should not be null" , key3Val2List != null );
22662307 assertTrue ("key3 list val 2 should have 1 element" , key3Val2List .size () == 1 );
22672308 assertTrue ("key3 list val 2 list element 1 should be null" , key3Val2List .get (0 ) == null );
0 commit comments