diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriter.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriter.java deleted file mode 100644 index e379b568c68..00000000000 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriter.java +++ /dev/null @@ -1,212 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 java.io.Closeable; -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayDeque; -import java.util.Deque; - -/** Simple Json generator that does no validation. */ -public class JsonWriter implements Closeable { - private final Writer mWriter; - private final Deque mScopes; - - public JsonWriter(Writer writer) { - mWriter = writer; - mScopes = new ArrayDeque<>(); - } - - public JsonWriter beginArray() throws IOException { - open(Scope.EMPTY_ARRAY, '['); - return this; - } - - public JsonWriter endArray() throws IOException { - close(']'); - return this; - } - - public JsonWriter beginObject() throws IOException { - open(Scope.EMPTY_OBJECT, '{'); - return this; - } - - public JsonWriter endObject() throws IOException { - close('}'); - return this; - } - - public JsonWriter name(String name) throws IOException { - if (name == null) { - throw new NullPointerException("name can not be null"); - } - beforeName(); - string(name); - mWriter.write(':'); - return this; - } - - public JsonWriter value(String value) throws IOException { - if (value == null) { - return nullValue(); - } - beforeValue(); - string(value); - return this; - } - - public JsonWriter nullValue() throws IOException { - beforeValue(); - mWriter.write("null"); - return this; - } - - public JsonWriter rawValue(String json) throws IOException { - beforeValue(); - mWriter.write(json); - return this; - } - - public JsonWriter value(boolean value) throws IOException { - beforeValue(); - mWriter.write(value ? "true" : "false"); - return this; - } - - public JsonWriter value(double value) throws IOException { - beforeValue(); - mWriter.append(Double.toString(value)); - return this; - } - - public JsonWriter value(long value) throws IOException { - beforeValue(); - mWriter.write(Long.toString(value)); - return this; - } - - public JsonWriter value(Number value) throws IOException { - if (value == null) { - return nullValue(); - } - beforeValue(); - mWriter.append(value.toString()); - return this; - } - - @Override - public void close() throws IOException { - mWriter.close(); - } - - private void beforeValue() throws IOException { - Scope scope = mScopes.peek(); - switch (scope) { - case EMPTY_ARRAY: - replace(Scope.ARRAY); - break; - case EMPTY_OBJECT: - throw new IllegalArgumentException(Scope.EMPTY_OBJECT.name()); - case ARRAY: - mWriter.write(','); - break; - case OBJECT: - break; - default: - throw new IllegalStateException("Unknown scope: " + scope); - } - } - - private void beforeName() throws IOException { - Scope scope = mScopes.peek(); - switch (scope) { - case EMPTY_ARRAY: - case ARRAY: - throw new IllegalStateException("name not allowed in array"); - case EMPTY_OBJECT: - replace(Scope.OBJECT); - break; - case OBJECT: - mWriter.write(','); - break; - default: - throw new IllegalStateException("Unknown scope: " + scope); - } - } - - private void open(Scope scope, char bracket) throws IOException { - mScopes.push(scope); - mWriter.write(bracket); - } - - private void close(char bracket) throws IOException { - mScopes.pop(); - mWriter.write(bracket); - } - - private void string(String string) throws IOException { - mWriter.write('"'); - for (int i = 0, length = string.length(); i < length; i++) { - char c = string.charAt(i); - switch (c) { - case '\t': - mWriter.write("\\t"); - break; - - case '\b': - mWriter.write("\\b"); - break; - - case '\n': - mWriter.write("\\n"); - break; - - case '\r': - mWriter.write("\\r"); - break; - - case '\f': - mWriter.write("\\f"); - break; - - case '"': - case '\\': - mWriter.write('\\'); - mWriter.write(c); - break; - - case '\u2028': - case '\u2029': - mWriter.write(String.format("\\u%04x", (int) c)); - break; - - default: - if (c <= 0x1F) { - mWriter.write(String.format("\\u%04x", (int) c)); - } else { - mWriter.write(c); - } - break; - } - } - mWriter.write('"'); - } - - private void replace(Scope scope) { - mScopes.pop(); - mScopes.push(scope); - } - - private enum Scope { - EMPTY_OBJECT, - OBJECT, - EMPTY_ARRAY, - ARRAY - } -} diff --git a/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java b/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java index ab46dc7f72d..d91dc0220b9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java +++ b/ReactAndroid/src/main/java/com/facebook/react/bridge/JsonWriterHelper.java @@ -6,22 +6,121 @@ */ package com.facebook.react.bridge; +import android.util.JsonWriter; import java.io.IOException; import java.util.List; import java.util.Map; /** Helper for generating JSON for lists and maps. */ -class JsonWriterHelper { +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: + readableMapValue(writer, value.asMap()); + break; + case Array: + readableArrayValue(writer, value.asArray()); + 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: + readableMapValue(writer, value.getMap(key)); + break; + case Array: + readableArrayValue(writer, value.getArray(key)); + 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: + readableMapValue(writer, value.getMap(key)); + break; + case Array: + readableArrayValue(writer, value.getArray(key)); + 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()) { diff --git a/ReactAndroid/src/test/java/com/facebook/react/bridge/JsonWriterTest.java b/ReactAndroid/src/test/java/com/facebook/react/bridge/JsonWriterTest.java deleted file mode 100644 index ea031b3c28d..00000000000 --- a/ReactAndroid/src/test/java/com/facebook/react/bridge/JsonWriterTest.java +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its 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 static org.fest.assertions.api.Assertions.assertThat; - -import java.io.IOException; -import java.io.StringWriter; -import org.junit.Test; - -public class JsonWriterTest { - private final StringWriter mStringWriter; - private final JsonWriter mWriter; - - public JsonWriterTest() { - mStringWriter = new StringWriter(); - mWriter = new JsonWriter(mStringWriter); - } - - @Test - public void emptyObject() throws IOException { - mWriter.beginObject(); - mWriter.endObject(); - verify("{}"); - } - - @Test - public void emptyNestedObject() throws IOException { - mWriter.beginObject(); - mWriter.beginObject(); - mWriter.endObject(); - mWriter.endObject(); - verify("{{}}"); - } - - @Test - public void emptyArray() throws IOException { - mWriter.beginArray(); - mWriter.endArray(); - verify("[]"); - } - - @Test - public void emptyNestedArray() throws IOException { - mWriter.beginArray(); - mWriter.beginArray(); - mWriter.endArray(); - mWriter.endArray(); - verify("[[]]"); - } - - @Test - public void smallObject() throws IOException { - mWriter.beginObject(); - mWriter.name("hello").value(true); - mWriter.name("hello_again").value("hi!"); - mWriter.endObject(); - verify("{\"hello\":true,\"hello_again\":\"hi!\"}"); - } - - @Test - public void smallArray() throws IOException { - mWriter.beginArray(); - mWriter.value(true); - mWriter.value(1); - mWriter.value(1.0); - mWriter.value("hi!"); - mWriter.endArray(); - verify("[true,1,1.0,\"hi!\"]"); - } - - @Test - public void string() throws IOException { - mWriter.beginObject(); - mWriter.name("string").value("hello!"); - mWriter.endObject(); - verify("{\"string\":\"hello!\"}"); - } - - @Test - public void complexString() throws IOException { - mWriter.beginObject(); - mWriter.name("string").value("\t\uD83D\uDCA9"); - mWriter.endObject(); - verify("{\"string\":\"\\t\uD83D\uDCA9\"}"); - } - - private void verify(String expected) throws IOException { - mWriter.close(); - assertThat(mStringWriter.getBuffer().toString()).isEqualTo(expected); - } -}