content: package com.rnapi;
  
  import android.support.annotation.Nullable;
  
  import com.facebook.react.bridge.Arguments;
  import com.facebook.react.bridge.ReadableArray;
  import com.facebook.react.bridge.ReadableMap;
  import com.facebook.react.bridge.ReadableMapKeySetIterator;
  import com.facebook.react.bridge.ReadableType;
  import com.facebook.react.bridge.WritableArray;
  import com.facebook.react.bridge.WritableMap;
  import com.facebook.react.bridge.WritableNativeArray;
  import com.facebook.react.bridge.WritableNativeMap;
  
  import org.json.JSONArray;
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  public class ConvertUtils {
      public static Map<String, Object> readableMapToMap(final @Nullable ReadableMap readableMap) {
          if (readableMap == null) {
              return new HashMap<>();
          }
  
          final ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
          if (!iterator.hasNextKey()) {
              return new HashMap<>();
          }
  
          final Map<String, Object> result = new HashMap<>();
          while (iterator.hasNextKey()) {
              final String key = iterator.nextKey();
              result.put(key, toObject(readableMap, key));
          }
  
          return result;
      }
  
      public static Object toObject(@Nullable ReadableMap readableMap, String key) {
          if (readableMap == null) {
              return null;
          }
  
          Object result;
  
          final ReadableType readableType = readableMap.getType(key);
          switch (readableType) {
              case Null:
                  result = key;
                  break;
              case Boolean:
                  result = readableMap.getBoolean(key);
                  break;
              case Number:
                  // Can be int or double.
                  double tmp = readableMap.getDouble(key);
                  if (tmp == (int) tmp) {
                      result = (int) tmp;
                  } else {
                      result = tmp;
                  }
                  break;
              case String:
                  result = readableMap.getString(key);
                  break;
              case Map:
                  result = readableMapToMap(readableMap.getMap(key));
                  break;
              case Array:
                  result = readableArrayToList(readableMap.getArray(key));
                  break;
              default:
                  throw new IllegalArgumentException("Could not convert object with key: " + key + ".");
          }
  
          return result;
      }
  
      /**
       * toList converts a {@link ReadableArray} into an ArrayList.
       *
       * @param readableArray The ReadableArray to be conveted.
       * @return An ArrayList containing the data that was in the ReadableArray.
       */
      public static List<Object> readableArrayToList(final @Nullable ReadableArray readableArray) {
          if (readableArray == null) {
              return null;
          }
  
          List<Object> result = new ArrayList<>(readableArray.size());
          for (int index = 0; index < readableArray.size(); index++) {
              final ReadableType readableType = readableArray.getType(index);
              switch (readableType) {
                  case Null:
                      result.add(String.valueOf(index));
                      break;
                  case Boolean:
                      result.add(readableArray.getBoolean(index));
                      break;
                  case Number:
                      // Can be int or double.
                      double tmp = readableArray.getDouble(index);
                      if (tmp == (int) tmp) {
                          result.add((int) tmp);
                      } else {
                          result.add(tmp);
                      }
                      break;
                  case String:
                      result.add(readableArray.getString(index));
                      break;
                  case Map:
                      result.add(readableMapToMap(readableArray.getMap(index)));
                      break;
                  case Array:
                      result = readableArrayToList(readableArray.getArray(index));
                      break;
                  default:
                      throw new IllegalArgumentException("Could not convert object with index: " + index + ".");
              }
          }
  
          return result;
      }
  
      /**
       * better
       *
       * @param jsonArray
       * @return
       * @throws JSONException
       */
      public static WritableArray jsonToReact(final JSONArray jsonArray) throws JSONException {
          final WritableArray writableArray = Arguments.createArray();
          for (int i = 0; i < jsonArray.length(); i++) {
              final Object value = jsonArray.get(i);
              if (value instanceof Float || value instanceof Double) {
                  writableArray.pushDouble(jsonArray.getDouble(i));
              } else if (value instanceof Number) {
                  writableArray.pushInt(jsonArray.getInt(i));
              } else if (value instanceof String) {
                  writableArray.pushString(jsonArray.getString(i));
              } else if (value instanceof Boolean) {
                  writableArray.pushBoolean(jsonArray.getBoolean(i));
              } else if (value instanceof JSONObject) {
                  writableArray.pushMap(jsonToReact(jsonArray.getJSONObject(i)));
              } else if (value instanceof JSONArray) {
                  writableArray.pushArray(jsonToReact(jsonArray.getJSONArray(i)));
              } else if (value == JSONObject.NULL) {
                  writableArray.pushNull();
              }
          }
          return writableArray;
      }
  
      /**
       * better
       *
       * @param jsonObject
       * @return
       * @throws JSONException
       */
      public static WritableMap jsonToReact(final JSONObject jsonObject) throws JSONException {
          final WritableMap writableMap = Arguments.createMap();
          final Iterator iterator = jsonObject.keys();
          while (iterator.hasNext()) {
              final String key = (String) iterator.next();
              final Object value = jsonObject.get(key);
              if (value instanceof Float || value instanceof Double) {
                  writableMap.putDouble(key, jsonObject.getDouble(key));
              } else if (value instanceof Number) {
                  writableMap.putInt(key, jsonObject.getInt(key));
              } else if (value instanceof String) {
                  writableMap.putString(key, jsonObject.getString(key));
              } else if (value instanceof JSONObject) {
                  writableMap.putMap(key, jsonToReact(jsonObject.getJSONObject(key)));
              } else if (value instanceof JSONArray) {
                  writableMap.putArray(key, jsonToReact(jsonObject.getJSONArray(key)));
              } else if (value instanceof Boolean) {
                  writableMap.putBoolean(key, jsonObject.getBoolean(key));
              } else if (value == JSONObject.NULL) {
                  writableMap.putNull(key);
              }
          }
          return writableMap;
      }
  
      public static WritableMap convertJsonToMap(JSONObject jsonObject) throws JSONException {
          WritableMap map = new WritableNativeMap();
  
          Iterator<String> iterator = jsonObject.keys();
          while (iterator.hasNext()) {
              String key = iterator.next();
              Object value = jsonObject.get(key);
              if (value instanceof JSONObject) {
                  map.putMap(key, convertJsonToMap((JSONObject) value));
              } else if (value instanceof JSONArray) {
                  map.putArray(key, convertJsonToArray((JSONArray) value));
              } else if (value instanceof Boolean) {
                  map.putBoolean(key, (Boolean) value);
              } else if (value instanceof Integer) {
                  map.putInt(key, (Integer) value);
              } else if (value instanceof Double) {
                  map.putDouble(key, (Double) value);
              } else if (value instanceof String) {
                  map.putString(key, (String) value);
              } else {
                  map.putString(key, value.toString());
              }
          }
          return map;
      }
  
      public static WritableArray convertJsonToArray(JSONArray jsonArray) throws JSONException {
          WritableArray array = new WritableNativeArray();
  
          for (int i = 0; i < jsonArray.length(); i++) {
              Object value = jsonArray.get(i);
              if (value instanceof JSONObject) {
                  array.pushMap(convertJsonToMap((JSONObject) value));
              } else if (value instanceof JSONArray) {
                  array.pushArray(convertJsonToArray((JSONArray) value));
              } else if (value instanceof Boolean) {
                  array.pushBoolean((Boolean) value);
              } else if (value instanceof Integer) {
                  array.pushInt((Integer) value);
              } else if (value instanceof Double) {
                  array.pushDouble((Double) value);
              } else if (value instanceof String) {
                  array.pushString((String) value);
              } else {
                  array.pushString(value.toString());
              }
          }
          return array;
      }
  
      public static JSONObject convertMapToJson(ReadableMap readableMap) throws JSONException {
          JSONObject object = new JSONObject();
          ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
          while (iterator.hasNextKey()) {
              String key = iterator.nextKey();
              switch (readableMap.getType(key)) {
                  case Null:
                      object.put(key, JSONObject.NULL);
                      break;
                  case Boolean:
                      object.put(key, readableMap.getBoolean(key));
                      break;
                  case Number:
                      object.put(key, readableMap.getDouble(key));
                      break;
                  case String:
                      object.put(key, readableMap.getString(key));
                      break;
                  case Map:
                      object.put(key, convertMapToJson(readableMap.getMap(key)));
                      break;
                  case Array:
                      object.put(key, convertArrayToJson(readableMap.getArray(key)));
                      break;
              }
          }
          return object;
      }
  
      public static JSONArray convertArrayToJson(ReadableArray readableArray) throws JSONException {
          JSONArray array = new JSONArray();
          for (int i = 0; i < readableArray.size(); i++) {
              switch (readableArray.getType(i)) {
                  case Null:
                      break;
                  case Boolean:
                      array.put(readableArray.getBoolean(i));
                      break;
                  case Number:
                      array.put(readableArray.getDouble(i));
                      break;
                  case String:
                      array.put(readableArray.getString(i));
                      break;
                  case Map:
                      array.put(convertMapToJson(readableArray.getMap(i)));
                      break;
                  case Array:
                      array.put(convertArrayToJson(readableArray.getArray(i)));
                      break;
              }
          }
          return array;
      }
  }
  