diff --git a/src/zutil/parser/json/JSONObjectInputStream.java b/src/zutil/parser/json/JSONObjectInputStream.java index 463b46f..499af04 100644 --- a/src/zutil/parser/json/JSONObjectInputStream.java +++ b/src/zutil/parser/json/JSONObjectInputStream.java @@ -29,6 +29,7 @@ import java.io.*; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -36,9 +37,11 @@ import javax.activation.UnsupportedDataTypeException; public class JSONObjectInputStream extends InputStream implements ObjectInput, Closeable{ private JSONParser parser; + private HashMap objCache; public JSONObjectInputStream(Reader in) { this.parser = new JSONParser(in); + this.objCache = new HashMap(); } public Object readObject() throws IOException { @@ -56,12 +59,18 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); + } finally { + objCache.clear(); } return null; } - protected static Object readObject(DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException { - Class objClass = Class.forName(json.getString("@class")); + protected Object readObject(DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException { + // See if the Object id is in the cache before continuing + if(json.getString("@object_id") != null && objCache.containsKey(json.getInt("@object_id"))) + return objCache.get(json.getInt("@object_id")); + + Class objClass = Class.forName(json.getString("@class")); Object obj = objClass.newInstance(); // Read all fields from the new object instance @@ -76,11 +85,14 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C json.get(field.getName()))); } } + // Add object to the cache + if(json.getString("@object_id") != null) + objCache.put(json.getInt("@object_id"), obj); return obj; } @SuppressWarnings({ "rawtypes", "unchecked" }) - protected static Object readValue(Class type, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException { + protected Object readValue(Class type, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException { // Field type is a primitive? if(type.isPrimitive() || String.class.isAssignableFrom(type)){ return readPrimitive(type, json); diff --git a/src/zutil/test/JSONSerializerTest.java b/src/zutil/test/JSONSerializerTest.java index 951bbf4..ce183f4 100644 --- a/src/zutil/test/JSONSerializerTest.java +++ b/src/zutil/test/JSONSerializerTest.java @@ -34,23 +34,6 @@ import zutil.parser.json.JSONObjectOutputStream; public class JSONSerializerTest{ - @Test - public void testOutputSerializer() throws InterruptedException, IOException, ClassNotFoundException{ - TestClass sourceObj = new TestClass().init(); - - StringOutputStream bout = new StringOutputStream(); - JSONObjectOutputStream out = new JSONObjectOutputStream(bout); - out.writeObject(sourceObj); - out.flush(); - out.close(); - String data = bout.toString(); - System.out.println(data); - - assertEquals( - "{\"str\": \"1234\", \"@class\": \"zutil.test.JSONSerializerTest$TestClass\", \"obj1\": {\"@class\": \"zutil.test.JSONSerializerTest$TestObj\", \"value\": \"42\", \"@object_id\": 2}, \"obj2\": {\"@class\": \"zutil.test.JSONSerializerTest$TestObj\", \"value\": \"42\", \"@object_id\": 3}, \"decimal\": \"1.1\", \"@object_id\": 1}", - data); - } - @Test public void testJavaLegacySerialize() throws InterruptedException, IOException, ClassNotFoundException{ TestClass sourceObj = new TestClass().init(); @@ -70,6 +53,18 @@ public class JSONSerializerTest{ assertEquals( sourceObj, targetObj ); } + @Test + public void testOutputSerializerWithPrimitives() throws InterruptedException, IOException, ClassNotFoundException{ + TestClass sourceObj = new TestClass().init(); + + String data = writeObjectToJson(sourceObj); + data = data.replace("\"", "'"); + + assertEquals( + "{'str': '1234', '@class': 'zutil.test.JSONSerializerTest$TestClass', 'obj1': {'@class': 'zutil.test.JSONSerializerTest$TestObj', 'value': '42', '@object_id': 2}, 'obj2': {'@class': 'zutil.test.JSONSerializerTest$TestObj', 'value': '42', '@object_id': 3}, 'decimal': '1.1', '@object_id': 1}", + data); + } + @Test public void testInputSerializerWithPrimitives() throws InterruptedException, IOException, ClassNotFoundException{ TestClass sourceObj = new TestClass().init(); @@ -79,6 +74,18 @@ public class JSONSerializerTest{ assertEquals( sourceObj, targetObj ); } + @Test + public void testOutputSerializerWithClones() throws InterruptedException, IOException, ClassNotFoundException{ + TestClassObjClone sourceObj = new TestClassObjClone().init(); + + String data = writeObjectToJson(sourceObj); + data = data.replace("\"", "'"); + + assertEquals( + "{'@class': 'zutil.test.JSONSerializerTest$TestClassObjClone', 'obj1': {'@class': 'zutil.test.JSONSerializerTest$TestObj', 'value': '42', '@object_id': 2}, 'obj2': {'@class': 'zutil.test.JSONSerializerTest$TestObj', '@object_id': 2}, '@object_id': 1}", + data); + } + @Test public void testInputSerializerWithClones() throws InterruptedException, IOException, ClassNotFoundException{ TestClassObjClone sourceObj = new TestClassObjClone().init(); @@ -93,25 +100,35 @@ public class JSONSerializerTest{ /******************* Utility Functions ************************************/ + private static T sendReceiveObject(T sourceObj) throws IOException{ + return readObjectFromJson( + writeObjectToJson(sourceObj)); + } + @SuppressWarnings("unchecked") - private static T sendReceiveObject(T sourceObj) throws IOException{ - // Send - StringOutputStream bout = new StringOutputStream(); - JSONObjectOutputStream out = new JSONObjectOutputStream(bout); - out.writeObject(sourceObj); - out.flush(); - out.close(); - String data = bout.toString(); - System.out.println(data); - - // Receive - StringReader bin = new StringReader(data); + private static T readObjectFromJson(String json) throws IOException{ + StringReader bin = new StringReader(json); JSONObjectInputStream in = new JSONObjectInputStream(bin); T targetObj = (T) in.readObject(); in.close(); + return targetObj; } + private static String writeObjectToJson(T sourceObj) throws IOException{ + StringOutputStream bout = new StringOutputStream(); + JSONObjectOutputStream out = new JSONObjectOutputStream(bout); + + out.writeObject(sourceObj); + out.flush(); + out.close(); + + String data = bout.toString(); + System.out.println(data); + + return data; + } + /******************** Test Classes ************************************/ public static class TestClass implements Serializable{ @@ -149,9 +166,9 @@ public class JSONSerializerTest{ public boolean equals(Object obj){ return obj instanceof TestClassObjClone && - this.obj1.equals(((TestClass)obj).obj1) && + this.obj1.equals(((TestClassObjClone)obj).obj1) && this.obj1 == this.obj2 && - ((TestClass)obj).obj1 == ((TestClass)obj).obj2; + ((TestClassObjClone)obj).obj1 == ((TestClassObjClone)obj).obj2; } }