diff --git a/elemental/src/elemental/json/JsonValue.java b/elemental/src/elemental/json/JsonValue.java index f4f21543cee..c0de7ab73b3 100644 --- a/elemental/src/elemental/json/JsonValue.java +++ b/elemental/src/elemental/json/JsonValue.java @@ -15,10 +15,12 @@ */ package elemental.json; +import java.io.Serializable; + /** * Base interface for all Json values. */ -public interface JsonValue { +public interface JsonValue extends Serializable { /** * Coerces underlying value to boolean according to the rules of Javascript coercion. diff --git a/elemental/src/elemental/json/impl/JreJsonArray.java b/elemental/src/elemental/json/impl/JreJsonArray.java index 5a6a240967c..c31ba33ba87 100644 --- a/elemental/src/elemental/json/impl/JreJsonArray.java +++ b/elemental/src/elemental/json/impl/JreJsonArray.java @@ -15,9 +15,13 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.List; +import elemental.json.Json; import elemental.json.JsonArray; import elemental.json.JsonBoolean; import elemental.json.JsonFactory; @@ -32,9 +36,11 @@ */ public class JreJsonArray extends JreJsonValue implements JsonArray { - private ArrayList arrayValues = new ArrayList(); + private static final long serialVersionUID = 1L; - private JsonFactory factory; + private transient ArrayList arrayValues = new ArrayList(); + + private transient JsonFactory factory; public JreJsonArray(JsonFactory factory) { this.factory = factory; @@ -162,4 +168,16 @@ public void traverse(elemental.json.impl.JsonVisitor visitor, } visitor.endVisit(this, ctx); } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + JreJsonArray instance = parseJson(stream); + this.factory = Json.instance(); + this.arrayValues = instance.arrayValues; + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(toJson()); + } + } diff --git a/elemental/src/elemental/json/impl/JreJsonBoolean.java b/elemental/src/elemental/json/impl/JreJsonBoolean.java index a947fd378d3..e48895f086b 100644 --- a/elemental/src/elemental/json/impl/JreJsonBoolean.java +++ b/elemental/src/elemental/json/impl/JreJsonBoolean.java @@ -15,6 +15,11 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import elemental.json.Json; import elemental.json.JsonBoolean; import elemental.json.JsonType; import elemental.json.JsonValue; @@ -24,7 +29,9 @@ */ public class JreJsonBoolean extends JreJsonValue implements JsonBoolean { - private boolean bool; + private static final long serialVersionUID = 1L; + + private transient boolean bool; public JreJsonBoolean(boolean bool) { this.bool = bool; } @@ -69,4 +76,15 @@ public void traverse(elemental.json.impl.JsonVisitor visitor, JsonContext ctx) { public String toJson() throws IllegalStateException { return String.valueOf(bool); } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + JreJsonBoolean instance = parseJson(stream); + this.bool = instance.bool; + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(toJson()); + } + } diff --git a/elemental/src/elemental/json/impl/JreJsonNull.java b/elemental/src/elemental/json/impl/JreJsonNull.java index 25acab12df5..7336417adbb 100644 --- a/elemental/src/elemental/json/impl/JreJsonNull.java +++ b/elemental/src/elemental/json/impl/JreJsonNull.java @@ -15,6 +15,11 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; + import elemental.json.JsonNull; import elemental.json.JsonType; import elemental.json.JsonValue; @@ -24,6 +29,8 @@ */ public class JreJsonNull extends JreJsonValue implements JsonNull { + private static final long serialVersionUID = 1L; + public static final JsonNull NULL_INSTANCE = new JreJsonNull(); @Override @@ -62,4 +69,9 @@ public void traverse(JsonVisitor visitor, elemental.json.impl.JsonContext ctx) { public String toJson() { return null; } + + private Object readResolve() throws ObjectStreamException { + return NULL_INSTANCE; + } + } diff --git a/elemental/src/elemental/json/impl/JreJsonNumber.java b/elemental/src/elemental/json/impl/JreJsonNumber.java index 4fb2842c350..26c6e614db1 100644 --- a/elemental/src/elemental/json/impl/JreJsonNumber.java +++ b/elemental/src/elemental/json/impl/JreJsonNumber.java @@ -15,6 +15,11 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import elemental.json.Json; import elemental.json.JsonNumber; import elemental.json.JsonType; import elemental.json.JsonValue; @@ -24,7 +29,9 @@ */ public class JreJsonNumber extends JreJsonValue implements JsonNumber { - private double number; + private static final long serialVersionUID = 1L; + + private transient double number; public JreJsonNumber(double number) { this.number = number; @@ -74,4 +81,14 @@ public String toJson() { } return toReturn; } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + JreJsonNumber instance = parseJson(stream); + this.number = instance.number; + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(toJson()); + } } diff --git a/elemental/src/elemental/json/impl/JreJsonObject.java b/elemental/src/elemental/json/impl/JreJsonObject.java index 992f9a0fafe..732def25443 100755 --- a/elemental/src/elemental/json/impl/JreJsonObject.java +++ b/elemental/src/elemental/json/impl/JreJsonObject.java @@ -15,6 +15,9 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -22,6 +25,7 @@ import java.util.List; import java.util.Map; +import elemental.json.Json; import elemental.json.JsonArray; import elemental.json.JsonBoolean; import elemental.json.JsonFactory; @@ -36,6 +40,8 @@ */ public class JreJsonObject extends JreJsonValue implements JsonObject { + private static final long serialVersionUID = 1L; + private static List stringifyOrder(String[] keys) { List toReturn = new ArrayList(); List nonNumeric = new ArrayList(); @@ -51,8 +57,8 @@ private static List stringifyOrder(String[] keys) { return toReturn; } - private JsonFactory factory; - private Map map = new LinkedHashMap(); + private transient JsonFactory factory; + private transient Map map = new LinkedHashMap(); public JreJsonObject(JsonFactory factory) { this.factory = factory; @@ -175,4 +181,16 @@ public void traverse(JsonVisitor visitor, JsonContext ctx) { } visitor.endVisit(this, ctx); } + + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + JreJsonObject instance = parseJson(stream); + this.factory = Json.instance(); + this.map = instance.map; + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(toJson()); + } + } diff --git a/elemental/src/elemental/json/impl/JreJsonString.java b/elemental/src/elemental/json/impl/JreJsonString.java index f2822455209..690ea10bfec 100644 --- a/elemental/src/elemental/json/impl/JreJsonString.java +++ b/elemental/src/elemental/json/impl/JreJsonString.java @@ -15,6 +15,11 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import elemental.json.Json; import elemental.json.JsonString; import elemental.json.JsonType; import elemental.json.JsonValue; @@ -24,7 +29,9 @@ */ public class JreJsonString extends JreJsonValue implements JsonString { - private String string; + private static final long serialVersionUID = 1L; + + private transient String string; public JreJsonString(String string) { this.string = string; @@ -78,4 +85,15 @@ public void traverse(JsonVisitor visitor, JsonContext ctx) { public String toJson() throws IllegalStateException { return JsonUtil.quote(getString()); } + + private void readObject(ObjectInputStream stream) throws IOException, + ClassNotFoundException { + JreJsonString instance = parseJson(stream); + this.string = instance.string; + } + + private void writeObject(ObjectOutputStream stream) throws IOException { + stream.writeObject(toJson()); + } + } diff --git a/elemental/src/elemental/json/impl/JreJsonValue.java b/elemental/src/elemental/json/impl/JreJsonValue.java index 313f8fb9a03..94eccca307c 100644 --- a/elemental/src/elemental/json/impl/JreJsonValue.java +++ b/elemental/src/elemental/json/impl/JreJsonValue.java @@ -15,6 +15,10 @@ */ package elemental.json.impl; +import java.io.IOException; +import java.io.ObjectInputStream; + +import elemental.json.Json; import elemental.json.JsonValue; /** @@ -28,4 +32,10 @@ public abstract class JreJsonValue implements JsonValue { public Object toNative() { return this; } + + protected static T parseJson(ObjectInputStream stream) + throws ClassNotFoundException, IOException { + String jsonString = (String) stream.readObject(); + return Json.instance().parse(jsonString); + } } diff --git a/elemental/tests/elemental/json/impl/JreJsonSerialization.java b/elemental/tests/elemental/json/impl/JreJsonSerialization.java new file mode 100644 index 00000000000..a3097a79fa9 --- /dev/null +++ b/elemental/tests/elemental/json/impl/JreJsonSerialization.java @@ -0,0 +1,114 @@ +package elemental.json.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import junit.framework.TestCase; +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonNull; +import elemental.json.JsonObject; +import elemental.json.JsonValue; + +public class JreJsonSerialization extends TestCase { + + public void testSerializeNull() throws Exception { + JsonNull null1 = Json.createNull(); + JsonNull null2 = Json.createNull(); + JsonValue out = serializeDeserialize(null1); + assertJsonEquals(null1, out); + assertSame(null1, out); + assertSame(null2, out); + assertSame(JreJsonNull.NULL_INSTANCE, out); + } + + public void testSerializeObject() throws Exception { + JsonObject foo = Json.createObject(); + foo.put("true", true); + foo.put("string", "string"); + foo.put("number", 1.25); + + JsonObject subObject = Json.createObject(); + subObject.put("false", false); + subObject.put("string2", "string2"); + subObject.put("number", -151); + + JsonArray subArray = Json.createArray(); + subArray.set(0, true); + subArray.set(1, 1); + subArray.set(2, "2"); + + foo.put("object", subObject); + foo.put("array", subArray); + foo.put("null", Json.createNull()); + + assertJsonEqualsAfterSerialization(foo); + } + + public void testSerializeArray() throws Exception { + JsonObject subObject = Json.createObject(); + subObject.put("false", false); + subObject.put("string2", "string2"); + subObject.put("number", -151); + + JsonArray subArray = Json.createArray(); + subArray.set(0, true); + subArray.set(1, 1); + subArray.set(2, "2"); + + JsonArray array = Json.createArray(); + array.set(0, true); + array.set(1, false); + array.set(2, 2); + array.set(3, "3"); + array.set(4, subObject); + array.set(5, subArray); + + assertJsonEqualsAfterSerialization(array); + } + + public void testSerializeBoolean() throws Exception { + assertJsonEqualsAfterSerialization(Json.create(true)); + assertJsonEqualsAfterSerialization(Json.create(false)); + } + + public void testSerializeString() throws Exception { + assertJsonEqualsAfterSerialization(Json.create("foo")); + assertJsonEqualsAfterSerialization(Json.create("")); + } + + public void testSerializeNumber() throws Exception { + assertJsonEqualsAfterSerialization(Json.create(0)); + assertJsonEqualsAfterSerialization(Json.create(-1.213123123)); + } + + private void assertJsonEqualsAfterSerialization( + T in) throws Exception { + T out = serializeDeserialize(in); + assertNotSame(in, out); + assertJsonEquals(in, out); + } + + private void assertJsonEquals(JsonValue a, JsonValue b) { + assertEquals(a.toJson(), b.toJson()); + } + + @SuppressWarnings("unchecked") + public T serializeDeserialize( + T originalJsonValue) throws Exception { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(buffer); + out.writeObject(originalJsonValue); + out.close(); + + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream( + buffer.toByteArray())); + T processedJsonValue = (T) in.readObject(); + in.close(); + return processedJsonValue; + } + +}