1 /* 2 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 3 * 4 * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 5 * copy, modify, and distribute this software in source code or binary form for use 6 * in connection with the web services and APIs provided by Facebook. 7 * 8 * As with any software that integrates with the Facebook platform, your use of 9 * this software is subject to the Facebook Developer Principles and Policies 10 * [http://developers.facebook.com/policy/]. This copyright notice shall be 11 * included in all copies or substantial portions of the software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 */ 20 21 package host.exp.exponent.utils 22 23 import android.os.Bundle 24 import org.json.JSONArray 25 import org.json.JSONException 26 import org.json.JSONObject 27 28 /** 29 * Referenced from [com.facebook.internal.BundleJSONConverter] 30 * https://github.com/facebook/facebook-android-sdk/blob/main/facebook-core/src/main/java/com/facebook/internal/BundleJSONConverter.kt 31 * 32 * com.facebook.internal is solely for the use of other packages within the Facebook SDK for 33 * Android. Use of any of the classes in this package is unsupported, and they may be modified or 34 * removed without warning at any time. 35 * 36 * A helper class that can round trip between JSON and Bundle objects that contains the types: 37 * Boolean, Integer, Long, Double, String If other types are found, an IllegalArgumentException is 38 * thrown. 39 */ 40 41 object BundleJSONConverter { 42 private val SETTERS: MutableMap<Class<*>, Setter> = HashMap() 43 44 @JvmStatic 45 @Throws(JSONException::class) convertToJSONnull46 fun convertToJSON(bundle: Bundle): JSONObject { 47 val json = JSONObject() 48 for (key in bundle.keySet()) { 49 val value = 50 bundle[key] // Null is not supported. 51 ?: continue 52 53 // Special case List<String> as getClass would not work, since List is an interface 54 if (value is List<*>) { 55 val jsonArray = JSONArray() 56 val listValue = value as List<String> 57 for (stringValue in listValue) { 58 jsonArray.put(stringValue) 59 } 60 json.put(key, jsonArray) 61 continue 62 } 63 64 // Special case Bundle as it's one way, on the return it will be JSONObject 65 if (value is Bundle) { 66 json.put(key, convertToJSON(value)) 67 continue 68 } 69 val setter = 70 SETTERS[value.javaClass] 71 ?: throw IllegalArgumentException("Unsupported type: " + value.javaClass) 72 setter.setOnJSON(json, key, value) 73 } 74 return json 75 } 76 77 @JvmStatic 78 @Throws(JSONException::class) convertToBundlenull79 fun convertToBundle(jsonObject: JSONObject): Bundle { 80 val bundle = Bundle() 81 val jsonIterator = jsonObject.keys() 82 while (jsonIterator.hasNext()) { 83 val key = jsonIterator.next() 84 val value = jsonObject[key] 85 if (value === JSONObject.NULL) { 86 // Null is not supported. 87 continue 88 } 89 90 // Special case JSONObject as it's one way, on the return it would be Bundle. 91 if (value is JSONObject) { 92 bundle.putBundle(key, convertToBundle(value)) 93 continue 94 } 95 val setter = 96 SETTERS[value.javaClass] 97 ?: throw IllegalArgumentException("Unsupported type: " + value.javaClass) 98 setter.setOnBundle(bundle, key, value) 99 } 100 return bundle 101 } 102 103 interface Setter { setOnBundlenull104 @Throws(JSONException::class) fun setOnBundle(bundle: Bundle, key: String, value: Any) 105 106 @Throws(JSONException::class) fun setOnJSON(json: JSONObject, key: String, value: Any) 107 } 108 109 init { 110 SETTERS[java.lang.Boolean::class.java] = 111 object : Setter { 112 @Throws(JSONException::class) 113 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 114 bundle.putBoolean(key, value as Boolean) 115 } 116 117 @Throws(JSONException::class) 118 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 119 json.put(key, value) 120 } 121 } 122 SETTERS[java.lang.Integer::class.java] = 123 object : Setter { 124 @Throws(JSONException::class) 125 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 126 bundle.putInt(key, value as Int) 127 } 128 129 @Throws(JSONException::class) 130 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 131 json.put(key, value) 132 } 133 } 134 SETTERS[java.lang.Long::class.java] = 135 object : Setter { 136 @Throws(JSONException::class) 137 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 138 bundle.putLong(key, value as Long) 139 } 140 141 @Throws(JSONException::class) 142 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 143 json.put(key, value) 144 } 145 } 146 SETTERS[java.lang.Double::class.java] = 147 object : Setter { 148 @Throws(JSONException::class) 149 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 150 bundle.putDouble(key, value as Double) 151 } 152 153 @Throws(JSONException::class) 154 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 155 json.put(key, value) 156 } 157 } 158 SETTERS[String::class.java] = 159 object : Setter { 160 @Throws(JSONException::class) 161 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 162 bundle.putString(key, value as String) 163 } 164 165 @Throws(JSONException::class) 166 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 167 json.put(key, value) 168 } 169 } 170 SETTERS[Array<String>::class.java] = 171 object : Setter { 172 @Throws(JSONException::class) 173 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 174 throw IllegalArgumentException("Unexpected type from JSON") 175 } 176 177 @Throws(JSONException::class) 178 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 179 val jsonArray = JSONArray() 180 for (stringValue in value as Array<String>) { 181 jsonArray.put(stringValue) 182 } 183 json.put(key, jsonArray) 184 } 185 } 186 SETTERS[JSONArray::class.java] = 187 object : Setter { 188 @Throws(JSONException::class) 189 override fun setOnBundle(bundle: Bundle, key: String, value: Any) { 190 val jsonArray = value as JSONArray 191 val stringArrayList = ArrayList<String>() 192 // Empty list, can't even figure out the type, assume an ArrayList<String> 193 if (jsonArray.length() == 0) { 194 bundle.putStringArrayList(key, stringArrayList) 195 return 196 } 197 198 // Only strings are supported for now 199 for (i in 0 until jsonArray.length()) { 200 val current = jsonArray[i] 201 if (current is String) { 202 stringArrayList.add(current) 203 } else { 204 throw IllegalArgumentException("Unexpected type in an array: " + current.javaClass) 205 } 206 } 207 bundle.putStringArrayList(key, stringArrayList) 208 } 209 210 @Throws(JSONException::class) 211 override fun setOnJSON(json: JSONObject, key: String, value: Any) { 212 throw IllegalArgumentException("JSONArray's are not supported in bundles.") 213 } 214 } 215 } 216 } 217