From bc0717c6cc56fe0a9a7c066c9f8bf1ab2450bb54 Mon Sep 17 00:00:00 2001 From: Guichaguri Date: Thu, 20 Jul 2017 02:37:42 -0700 Subject: [PATCH] Android: Added support to arrays in toBundle Summary: The support for `ReadableArray` in `toBundle` was never implemented, throwing an `UnsupportedOperationException` when trying to convert an array. * Created `toList` -- A method that converts a `ReadableArray` to an `ArrayList` * Modified `toBundle` to support arrays using `toList` * Created `fromList` -- A method that converts a `List` to a `WritableArray` * Modified `fromBundle` to also support lists using `fromList` This PR allows `toBundle` and `fromBundle` (as well as `toList` and `fromList`) to work consistently without loosing information. **Test Plan** I've created three different arrays: one full of integers, one full of strings, and one mixed (with a integer, a boolean, a string, null, a map with a string and a boolean array), putting all of them inside a map. After converting the map to a `Bundle` using `toBundle`, the integer array was retrieved through `Bundle.getIntegerArrayList`, the string array through `Bundle.getStringArrayList` and the mixed array through `Bundle.get` (casting it to an `ArrayList`) After checking whether each value from the bundle was correct, I converted the bundle back to a map using `fromBundle`, and checked again every value. The code and results from the test can be found in [this gist](https://gist.github.com/Guichaguri/5c7574b31f9584b6a9a0c182fd940a86). Closes https://github.com/facebook/react-native/pull/15056 Differential Revision: D5460966 Pulled By: javache fbshipit-source-id: a11b450eae4186e68bed7b8ce7dea8e5982e689a --- .../com/facebook/react/bridge/Arguments.java | 92 ++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java index 262dab252746b8..267a9ca8e5f210 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/Arguments.java @@ -11,6 +11,7 @@ import java.lang.reflect.Array; import java.util.AbstractList; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -235,6 +236,40 @@ public static WritableArray fromArray(Object array) { return catalystArray; } + /** + * Convert a {@link List} to a {@link WritableArray}. + * + * @param list the list to convert. Supported value types are: {@code null}, {@code String}, {@code Bundle}, + * {@code List}, {@code Number}, {@code Boolean}, and all array types supported in {@link #fromArray(Object)}. + * @return the converted {@link WritableArray} + * @throws IllegalArgumentException if one of the values from the passed list is none of the above types + */ + public static WritableArray fromList(List list) { + WritableArray catalystArray = createArray(); + for (Object obj : list) { + if (obj == null) { + catalystArray.pushNull(); + } else if (obj.getClass().isArray()) { + catalystArray.pushArray(fromArray(obj)); + } else if (obj instanceof Bundle) { + catalystArray.pushMap(fromBundle((Bundle) obj)); + } else if (obj instanceof List) { + catalystArray.pushArray(fromList((List) obj)); + } else if (obj instanceof String) { + catalystArray.pushString((String) obj); + } else if (obj instanceof Integer) { + catalystArray.pushInt((Integer) obj); + } else if (obj instanceof Number) { + catalystArray.pushDouble(((Number) obj).doubleValue()); + } else if (obj instanceof Boolean) { + catalystArray.pushBoolean((Boolean) obj); + } else { + throw new IllegalArgumentException("Unknown value type " + obj.getClass()); + } + } + return catalystArray; + } + /** * Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle * are: @@ -242,6 +277,7 @@ public static WritableArray fromArray(Object array) { * * @@ -269,6 +305,8 @@ public static WritableMap fromBundle(Bundle bundle) { map.putBoolean(key, (Boolean) value); } else if (value instanceof Bundle) { map.putMap(key, fromBundle((Bundle) value)); + } else if (value instanceof List) { + map.putArray(key, fromList((List) value)); } else { throw new IllegalArgumentException("Could not convert " + value.getClass()); } @@ -276,8 +314,58 @@ public static WritableMap fromBundle(Bundle bundle) { return map; } + /** + * Convert a {@link WritableArray} to a {@link ArrayList}. + * + * @param readableArray the {@link WritableArray} to convert. + * @return the converted {@link ArrayList}. + */ + @Nullable + public static ArrayList toList(@Nullable ReadableArray readableArray) { + if (readableArray == null) { + return null; + } + + ArrayList list = new ArrayList(); + + for (int i = 0; i < readableArray.size(); i++) { + switch (readableArray.getType(i)) { + case Null: + list.add(null); + break; + case Boolean: + list.add(readableArray.getBoolean(i)); + break; + case Number: + double number = readableArray.getDouble(i); + if (number == Math.rint(number)) { + // Add as an integer + list.add((int) number); + } else { + // Add as a double + list.add(number); + } + break; + case String: + list.add(readableArray.getString(i)); + break; + case Map: + list.add(toBundle(readableArray.getMap(i))); + break; + case Array: + list.add(toList(readableArray.getArray(i))); + break; + default: + throw new IllegalArgumentException("Could not convert object in array."); + } + } + + return list; + } + /** * Convert a {@link WritableMap} to a {@link Bundle}. + * Note: Each array is converted to an {@link ArrayList}. * * @param readableMap the {@link WritableMap} to convert. * @return the converted {@link Bundle}. @@ -312,8 +400,8 @@ public static Bundle toBundle(@Nullable ReadableMap readableMap) { bundle.putBundle(key, toBundle(readableMap.getMap(key))); break; case Array: - // TODO t8873322 - throw new UnsupportedOperationException("Arrays aren't supported yet."); + bundle.putSerializable(key, toList(readableMap.getArray(key))); + break; default: throw new IllegalArgumentException("Could not convert object with key: " + key + "."); }