|
24 | 24 | import com.fasterxml.jackson.core.json.JsonWriteFeature; |
25 | 25 | import com.fasterxml.jackson.databind.*; |
26 | 26 | import org.apache.commons.lang3.StringUtils; |
| 27 | +import org.apache.commons.lang3.mutable.MutableBoolean; |
27 | 28 | import org.apache.logging.log4j.Logger; |
28 | 29 | import org.json.JSONArray; |
29 | 30 | import org.json.JSONException; |
30 | 31 | import org.json.JSONObject; |
31 | 32 | import org.junit.Assert; |
32 | 33 | import org.junit.Test; |
33 | 34 | import org.labkey.api.action.ApiUsageException; |
| 35 | +import org.labkey.api.collections.CaseInsensitiveHashMap; |
34 | 36 | import org.labkey.api.data.Container; |
35 | 37 | import org.labkey.api.security.User; |
36 | 38 | import org.labkey.api.settings.AppProps; |
@@ -202,15 +204,20 @@ public static List<JSONObject> toJSONObjectList(JSONArray array) |
202 | 204 | return result; |
203 | 205 | } |
204 | 206 |
|
205 | | - // The new JSONObject.toMap() translates all JSONObjects into Maps and JSONArrays into Lists. In many cases, this is |
206 | | - // fine, but some existing code paths want to maintain the contained JSONObjects and JSONArrays. This method does |
207 | | - // that, acting more like the old JSONObject.toMap(). |
208 | | - public static void fillMapShallow(JSONObject json, Map<String, Object> map) |
| 207 | + /** |
| 208 | + * The new JSONObject.toMap() translates all JSONObjects into Maps and JSONArrays into Lists. In many cases, this is |
| 209 | + * fine, but some existing code paths want to maintain the contained JSONObjects and JSONArrays. This method does |
| 210 | + * that, acting more like the old JSONObject.toMap(). |
| 211 | + * @return whether there were duplicate values in the map (useful when filling a case-insensitive map) |
| 212 | + */ |
| 213 | + public static boolean fillMapShallow(JSONObject json, Map<String, Object> map) |
209 | 214 | { |
| 215 | + MutableBoolean hadDuplicates = new MutableBoolean(false); |
210 | 216 | json.keySet().forEach(key -> { |
211 | 217 | Object value = json.get(key); |
212 | | - map.put(key, JSONObject.NULL == value ? null : value); |
| 218 | + hadDuplicates.setValue(map.put(key, JSONObject.NULL == value ? null : value) != null || hadDuplicates.booleanValue()); |
213 | 219 | }); |
| 220 | + return hadDuplicates.booleanValue(); |
214 | 221 | } |
215 | 222 |
|
216 | 223 | // New JSONObject discards all properties with null values. This returns a JSONObject containing all Map values, |
@@ -461,6 +468,20 @@ public void testJsonString() |
461 | 468 | assertEquals(u.getUserId(), roundTripJson.get("user")); |
462 | 469 | } |
463 | 470 |
|
| 471 | + @Test |
| 472 | + public void testConflictingCase() |
| 473 | + { |
| 474 | + JSONObject json = new JSONObject(); |
| 475 | + json.put("foo", "bar"); |
| 476 | + json.put("x", "y"); |
| 477 | + assertFalse(fillMapShallow(json, new HashMap<>())); |
| 478 | + assertFalse(fillMapShallow(json, new CaseInsensitiveHashMap<>())); |
| 479 | + |
| 480 | + json.put("FOO", "BAR"); |
| 481 | + assertFalse(fillMapShallow(json, new HashMap<>())); |
| 482 | + assertTrue(fillMapShallow(json, new CaseInsensitiveHashMap<>())); |
| 483 | + } |
| 484 | + |
464 | 485 | @Test |
465 | 486 | public void testSanitize() |
466 | 487 | { |
|
0 commit comments