Commits

Anonymous committed 3ad7868

Implement JSONObject.wrap, and use it.

Bug: https://code.google.com/p/android/issues/detail?id=55114
Change-Id: Ic2e010ac616f24dda7b8abced7eb2fc84dc7d50e

Comments (0)

Files changed (4)

json/src/main/java/org/json/JSONArray.java

 
 package org.json;
 
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 
 // Note: this class was written without inspecting the non-free org.json sourcecode.
     /* Accept a raw type for API compatibility */
     public JSONArray(Collection copyFrom) {
         this();
-        Collection<?> copyFromTyped = (Collection<?>) copyFrom;
-        values.addAll(copyFromTyped);
+        if (copyFrom != null) {
+            for (Iterator it = copyFrom.iterator(); it.hasNext();) {
+                put(JSONObject.wrap(it.next()));
+            }
+        }
     }
 
     /**
     }
 
     /**
+     * Creates a new {@code JSONArray} with values from the given primitive array.
+     */
+    public JSONArray(Object array) throws JSONException {
+        if (!array.getClass().isArray()) {
+            throw new JSONException("Not a primitive array: " + array.getClass());
+        }
+        final int length = Array.getLength(array);
+        values = new ArrayList<Object>(length);
+        for (int i = 0; i < length; ++i) {
+            put(JSONObject.wrap(Array.get(array, i)));
+        }
+    }
+
+    /**
      * Returns the number of values in this array.
      */
     public int length() {

json/src/main/java/org/json/JSONObject.java

 package org.json;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
             if (key == null) {
                 throw new NullPointerException("key == null");
             }
-            nameValuePairs.put(key, entry.getValue());
+            nameValuePairs.put(key, wrap(entry.getValue()));
         }
     }
 
             throw new AssertionError();
         }
     }
+
+    /**
+     * Wraps the given object if necessary.
+     *
+     * <p>If the object is null or , returns {@link #NULL}.
+     * If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary.
+     * If the object is {@code NULL}, no wrapping is necessary.
+     * If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}.
+     * If the object is a {@code Map}, returns an equivalent {@code JSONObject}.
+     * If the object is a primitive wrapper type or {@code String}, returns the object.
+     * Otherwise if the object is from a {@code java} package, returns the result of {@code toString}.
+     * If wrapping fails, returns null.
+     */
+    public static Object wrap(Object o) {
+        if (o == null) {
+            return NULL;
+        }
+        if (o instanceof JSONArray || o instanceof JSONObject) {
+            return o;
+        }
+        if (o.equals(NULL)) {
+            return o;
+        }
+        try {
+            if (o instanceof Collection) {
+                return new JSONArray((Collection) o);
+            } else if (o.getClass().isArray()) {
+                return new JSONArray(o);
+            }
+            if (o instanceof Map) {
+                return new JSONObject((Map) o);
+            }
+            if (o instanceof Boolean ||
+                o instanceof Byte ||
+                o instanceof Character ||
+                o instanceof Double ||
+                o instanceof Float ||
+                o instanceof Integer ||
+                o instanceof Long ||
+                o instanceof Short ||
+                o instanceof String) {
+                return o;
+            }
+            if (o.getClass().getPackage().getName().startsWith("java.")) {
+                return o.toString();
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
 }

json/src/test/java/org/json/JSONObjectTest.java

 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
     public void testPutNullRemoves() throws JSONException {
         JSONObject object = new JSONObject();
         object.put("foo", "bar");
-        object.put("foo", null);
+        object.put("foo", (Collection) null);
         assertEquals(0, object.length());
         assertFalse(object.has("foo"));
         try {
         }
     }
 
-    public void testStringonstructorParseFail() {
+    public void testStringConstructorParseFail() {
         try {
             new JSONObject("{");
             fail();
     public void testNullValue() throws JSONException {
         JSONObject object = new JSONObject();
         object.put("foo", JSONObject.NULL);
-        object.put("bar", null);
+        object.put("bar", (Collection) null);
 
         // there are two ways to represent null; each behaves differently!
         assertTrue(object.has("foo"));
         } catch (JSONException e) {
         }
     }
+
+    public void test_wrap() throws Exception {
+        assertEquals(JSONObject.NULL, JSONObject.wrap(null));
+
+        JSONArray a = new JSONArray();
+        assertEquals(a, JSONObject.wrap(a));
+
+        JSONObject o = new JSONObject();
+        assertEquals(o, JSONObject.wrap(o));
+
+        assertEquals(JSONObject.NULL, JSONObject.wrap(JSONObject.NULL));
+
+        assertTrue(JSONObject.wrap(new byte[0]) instanceof JSONArray);
+        assertTrue(JSONObject.wrap(new ArrayList<String>()) instanceof JSONArray);
+        assertTrue(JSONObject.wrap(new HashMap<String, String>()) instanceof JSONObject);
+        assertTrue(JSONObject.wrap(Double.valueOf(0)) instanceof Double);
+        assertTrue(JSONObject.wrap("hello") instanceof String);
+        assertTrue(JSONObject.wrap(java.nio.channels.Selector.open()) instanceof String);
+    }
+
+    // https://code.google.com/p/android/issues/detail?id=55114
+    public void test_toString_listAsMapValue() throws Exception {
+        ArrayList<Object> list = new ArrayList<Object>();
+        list.add("a");
+        list.add(new ArrayList<String>());
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put("x", "l");
+        map.put("y", list);
+        assertEquals("{\"y\":[\"a\",[]],\"x\":\"l\"}", new JSONObject(map).toString());
+    }
 }

json/src/test/java/org/json/ParsingTest.java

                 result.put(key, canonicalize(object.get(key)));
             }
             return result;
+        } else if (input == null || input.equals(JSONObject.NULL)) {
+            return JSONObject.NULL;
         } else {
             return input;
         }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.