From 32b1b7c2a004d49cce7693376223a789aa9facae Mon Sep 17 00:00:00 2001 From: Fabrizio Cucci Date: Thu, 10 Apr 2025 06:26:02 -0700 Subject: [PATCH] Kotlinify JsonWriterHelper (#50619) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50619 As per title. Changelog: [Internal] Reviewed By: cortinico Differential Revision: D72782158 fbshipit-source-id: f81b60a1a965efe82e065d7426d26f69fc84b321 --- .../ReactAndroid/api/ReactAndroid.api | 8 +- .../react/bridge/JsonWriterHelper.java | 170 ------------------ .../facebook/react/bridge/JsonWriterHelper.kt | 132 ++++++++++++++ 3 files changed, 136 insertions(+), 174 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index d6a73c31079..a76ba013843 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -903,10 +903,10 @@ public final class com/facebook/react/bridge/JavaScriptModuleRegistry { public fun getJavaScriptModule (Lcom/facebook/react/bridge/CatalystInstance;Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule; } -public class com/facebook/react/bridge/JsonWriterHelper { - public fun ()V - public static fun readableArrayValue (Landroid/util/JsonWriter;Lcom/facebook/react/bridge/ReadableArray;)V - public static fun value (Landroid/util/JsonWriter;Ljava/lang/Object;)V +public final class com/facebook/react/bridge/JsonWriterHelper { + public static final field INSTANCE Lcom/facebook/react/bridge/JsonWriterHelper; + public static final fun readableArrayValue (Landroid/util/JsonWriter;Lcom/facebook/react/bridge/ReadableArray;)V + public static final fun value (Landroid/util/JsonWriter;Ljava/lang/Object;)V } public abstract interface class com/facebook/react/bridge/LifecycleEventListener { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java deleted file mode 100644 index 1593a7f6365..00000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.bridge; - -import android.util.JsonWriter; -import com.facebook.infer.annotation.Assertions; -import com.facebook.infer.annotation.Nullsafe; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -/** Helper for generating JSON for lists and maps. */ -@Nullsafe(Nullsafe.Mode.LOCAL) -public class JsonWriterHelper { - public static void value(JsonWriter writer, Object value) throws IOException { - if (value instanceof Map) { - mapValue(writer, (Map) value); - } else if (value instanceof List) { - listValue(writer, (List) value); - } else if (value instanceof ReadableMap) { - readableMapValue(writer, (ReadableMap) value); - } else if (value instanceof ReadableArray) { - readableArrayValue(writer, (ReadableArray) value); - } else if (value instanceof Dynamic) { - dynamicValue(writer, (Dynamic) value); - } else { - objectValue(writer, value); - } - } - - private static void dynamicValue(JsonWriter writer, Dynamic value) throws IOException { - switch (value.getType()) { - case Null: - writer.nullValue(); - break; - case Boolean: - writer.value(value.asBoolean()); - break; - case Number: - writer.value(value.asDouble()); - break; - case String: - writer.value(value.asString()); - break; - case Map: - ReadableMap map = value.asMap(); - Assertions.assertNotNull(map); - readableMapValue(writer, map); - break; - case Array: - ReadableArray array = value.asArray(); - Assertions.assertNotNull(array); - readableArrayValue(writer, array); - break; - default: - throw new IllegalArgumentException("Unknown data type: " + value.getType()); - } - } - - private static void readableMapValue(JsonWriter writer, ReadableMap value) throws IOException { - writer.beginObject(); - try { - ReadableMapKeySetIterator iterator = value.keySetIterator(); - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - writer.name(key); - switch (value.getType(key)) { - case Null: - writer.nullValue(); - break; - case Boolean: - writer.value(value.getBoolean(key)); - break; - case Number: - writer.value(value.getDouble(key)); - break; - case String: - writer.value(value.getString(key)); - break; - case Map: - ReadableMap map = value.getMap(key); - Assertions.assertNotNull(map); - readableMapValue(writer, map); - break; - case Array: - ReadableArray array = value.getArray(key); - Assertions.assertNotNull(array); - readableArrayValue(writer, array); - break; - default: - throw new IllegalArgumentException("Unknown data type: " + value.getType(key)); - } - } - } finally { - writer.endObject(); - } - } - - public static void readableArrayValue(JsonWriter writer, ReadableArray value) throws IOException { - writer.beginArray(); - try { - for (int key = 0; key < value.size(); ++key) { - switch (value.getType(key)) { - case Null: - writer.nullValue(); - break; - case Boolean: - writer.value(value.getBoolean(key)); - break; - case Number: - writer.value(value.getDouble(key)); - break; - case String: - writer.value(value.getString(key)); - break; - case Map: - ReadableMap map = value.getMap(key); - Assertions.assertNotNull(map); - readableMapValue(writer, map); - break; - case Array: - ReadableArray array = value.getArray(key); - Assertions.assertNotNull(array); - readableArrayValue(writer, array); - break; - default: - throw new IllegalArgumentException("Unknown data type: " + value.getType(key)); - } - } - } finally { - writer.endArray(); - } - } - - private static void mapValue(JsonWriter writer, Map map) throws IOException { - writer.beginObject(); - for (Map.Entry entry : map.entrySet()) { - writer.name(entry.getKey().toString()); - value(writer, entry.getValue()); - } - writer.endObject(); - } - - private static void listValue(JsonWriter writer, List list) throws IOException { - writer.beginArray(); - for (Object item : list) { - objectValue(writer, item); - } - writer.endArray(); - } - - private static void objectValue(JsonWriter writer, Object value) throws IOException { - if (value == null) { - writer.nullValue(); - } else if (value instanceof String) { - writer.value((String) value); - } else if (value instanceof Number) { - writer.value((Number) value); - } else if (value instanceof Boolean) { - writer.value((Boolean) value); - } else { - throw new IllegalArgumentException("Unknown value: " + value); - } - } -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.kt new file mode 100644 index 00000000000..3babfceaa57 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.kt @@ -0,0 +1,132 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.bridge + +import android.util.JsonWriter +import java.io.IOException + +/** Helper for generating JSON for lists and maps. */ +public object JsonWriterHelper { + @Throws(IOException::class) + @JvmStatic + public fun value(writer: JsonWriter, value: Any?) { + when (value) { + is Map<*, *> -> mapValue(writer, value) + is List<*> -> listValue(writer, value) + is ReadableMap -> readableMapValue(writer, value) + is ReadableArray -> readableArrayValue(writer, value) + is Dynamic -> dynamicValue(writer, value) + else -> objectValue(writer, value) + } + } + + @Throws(IOException::class) + private fun dynamicValue(writer: JsonWriter, value: Dynamic) { + when (value.type) { + ReadableType.Null -> writer.nullValue() + ReadableType.Boolean -> writer.value(value.asBoolean()) + ReadableType.Number -> writer.value(value.asDouble()) + ReadableType.String -> writer.value(value.asString()) + ReadableType.Map -> { + val map = value.asMap() + readableMapValue(writer, checkNotNull(map)) + } + ReadableType.Array -> { + val array = value.asArray() + readableArrayValue(writer, checkNotNull(array)) + } + else -> throw IllegalArgumentException("Unknown data type: ${value.type}") + } + } + + @Throws(IOException::class) + private fun readableMapValue(writer: JsonWriter, value: ReadableMap) { + writer.beginObject() + try { + val iterator = value.keySetIterator() + while (iterator.hasNextKey()) { + val key = iterator.nextKey() + writer.name(key) + when (value.getType(key)) { + ReadableType.Null -> writer.nullValue() + ReadableType.Boolean -> writer.value(value.getBoolean(key)) + ReadableType.Number -> writer.value(value.getDouble(key)) + ReadableType.String -> writer.value(value.getString(key)) + ReadableType.Map -> { + val map = value.getMap(key) + readableMapValue(writer, checkNotNull(map)) + } + ReadableType.Array -> { + val array = value.getArray(key) + readableArrayValue(writer, checkNotNull(array)) + } + else -> throw IllegalArgumentException("Unknown data type: ${value.getType(key)}") + } + } + } finally { + writer.endObject() + } + } + + @Throws(IOException::class) + @JvmStatic + public fun readableArrayValue(writer: JsonWriter, value: ReadableArray) { + writer.beginArray() + try { + for (i in 0 until value.size()) { + when (value.getType(i)) { + ReadableType.Null -> writer.nullValue() + ReadableType.Boolean -> writer.value(value.getBoolean(i)) + ReadableType.Number -> writer.value(value.getDouble(i)) + ReadableType.String -> writer.value(value.getString(i)) + ReadableType.Map -> { + val map = value.getMap(i) + readableMapValue(writer, checkNotNull(map)) + } + ReadableType.Array -> { + val array = value.getArray(i) + readableArrayValue(writer, checkNotNull(array)) + } + else -> throw IllegalArgumentException("Unknown data type: ${value.getType(i)}") + } + } + } finally { + writer.endArray() + } + } + + @Throws(IOException::class) + private fun mapValue(writer: JsonWriter, map: Map<*, *>) { + writer.beginObject() + for ((key, value) in map) { + writer.name(key.toString()) + this.value(writer, value) + } + writer.endObject() + } + + @Throws(IOException::class) + private fun listValue(writer: JsonWriter, list: List<*>) { + writer.beginArray() + for (item in list) { + objectValue(writer, item) + } + writer.endArray() + } + + @Throws(IOException::class) + private fun objectValue(writer: JsonWriter, value: Any?) { + when (value) { + null -> writer.nullValue() + is String -> writer.value(value) + is Number -> writer.value(value) + is Boolean -> writer.value(value) + else -> throw IllegalArgumentException("Unknown value: $value") + } + } +}