diff --git a/Zutil.iml b/Zutil.iml index 323bdf0..789635f 100644 --- a/Zutil.iml +++ b/Zutil.iml @@ -8,7 +8,6 @@ - @@ -20,5 +19,18 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/zutil/parser/json/JSONObjectInputStream.java b/src/zutil/parser/json/JSONObjectInputStream.java index fa80f3c..2418fe2 100644 --- a/src/zutil/parser/json/JSONObjectInputStream.java +++ b/src/zutil/parser/json/JSONObjectInputStream.java @@ -26,6 +26,7 @@ package zutil.parser.json; import sun.reflect.generics.reflectiveObjects.NotImplementedException; import zutil.ClassUtil; +import zutil.log.LogUtil; import zutil.parser.Base64Decoder; import zutil.parser.DataNode; @@ -38,8 +39,11 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; public class JSONObjectInputStream extends InputStream implements ObjectInput, Closeable{ + private static final Logger logger = LogUtil.getLogger(); protected static final String MD_OBJECT_ID = "@object_id"; protected static final String MD_CLASS = "@class"; @@ -89,32 +93,29 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C try{ DataNode root = parser.read(); if(root != null){ - return readObject(null, root); + return readObject(null, null, root); } - // TODO: Fix Exceptions - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } finally { + } catch (Exception e) { + logger.log(Level.WARNING, null, e); + } finally { objectCache.clear(); } return null; } - protected Object readObject(String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException { + protected Object readObject(Class type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException, NoSuchFieldException { // See if the Object id is in the cache before continuing if(json.getString("@object_id") != null && objectCache.containsKey(json.getInt(MD_OBJECT_ID))) return objectCache.get(json.getInt(MD_OBJECT_ID)); // Resolve the class Object obj = null; + // Try using explicit class + if(type != null){ + obj = type.newInstance(); + } // Try using metadata - if(json.getString(MD_CLASS) != null) { + else if(json.getString(MD_CLASS) != null) { Class objClass = Class.forName(json.getString(MD_CLASS)); obj = objClass.newInstance(); } @@ -123,8 +124,11 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C Class objClass = registeredClasses.get(key); obj = objClass.newInstance(); } - // Unknown Class - else return null; + // Unknown class + else { + logger.warning("Unknown type for key: '"+key+"'"); + return null; + } // Read all fields from the new object instance for(Field field : obj.getClass().getDeclaredFields()){ @@ -146,7 +150,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C } @SuppressWarnings({ "rawtypes", "unchecked" }) - protected Object readField(Class type, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException { + protected Object readField(Class type, String key, DataNode json) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedDataTypeException, NoSuchFieldException { // Field type is a primitive? if(type.isPrimitive() || String.class.isAssignableFrom(type)){ return readPrimitive(type, json); @@ -165,7 +169,7 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C else if(List.class.isAssignableFrom(type)){ List list = (List)type.newInstance(); for(int i=0; i type, Object value) throws UnsupportedDataTypeException, IllegalArgumentException, IllegalAccessException { - DataNode node; + DataNode node = null; if (type == int.class || type == Integer.class || type == long.class || @@ -151,8 +153,9 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput node = new DataNode(DataType.String); else throw new UnsupportedDataTypeException("Unsupported primitive data type: "+type.getName()); - - node.set(value.toString()); + + if(value != null) + node.set(value.toString()); return node; } diff --git a/src/zutil/parser/json/JSONWriter.java b/src/zutil/parser/json/JSONWriter.java index 2961808..aecd0a2 100644 --- a/src/zutil/parser/json/JSONWriter.java +++ b/src/zutil/parser/json/JSONWriter.java @@ -75,6 +75,11 @@ public class JSONWriter{ * @param root is the root node */ public void write(DataNode root){ + if(root == null){ + out.print("null"); + return; + } + boolean first = true; switch(root.getType()){ // Write Map diff --git a/test/zutil/test/JSONSerializerTest.java b/test/zutil/test/JSONSerializerTest.java index 4f00f67..ca3a351 100644 --- a/test/zutil/test/JSONSerializerTest.java +++ b/test/zutil/test/JSONSerializerTest.java @@ -108,7 +108,21 @@ public class JSONSerializerTest{ assertEquals( sourceObj, targetObj ); } - + + @Test + public void testSerializerWithNullFields() throws InterruptedException, IOException, ClassNotFoundException{ + TestClass sourceObj = new TestClass(); + + String data = writeObjectToJson(sourceObj, false); + data = data.replace("\"", "'"); + assertEquals( + "{'str': null, 'obj1': null, 'obj2': null, 'decimal': 0.0}", + data); + + TestClass targetObj = sendReceiveObject(sourceObj); + assertEquals( sourceObj, targetObj ); + } + /******************* Utility Functions ************************************/ @@ -127,9 +141,13 @@ public class JSONSerializerTest{ return targetObj; } - public static String writeObjectToJson(T sourceObj) throws IOException{ + public static String writeObjectToJson(T sourceObj) throws IOException{ + return writeObjectToJson(sourceObj, true); + } + public static String writeObjectToJson(T sourceObj, boolean metadata) throws IOException{ StringOutputStream bout = new StringOutputStream(); JSONObjectOutputStream out = new JSONObjectOutputStream(bout); + out.enableMetaData(metadata); out.writeObject(sourceObj); out.flush();