Fixed null field issues in JSON

This commit is contained in:
Ziver Koc 2015-10-07 22:32:26 +00:00
parent 0bb193fba3
commit 051f6fdcf8
5 changed files with 52 additions and 23 deletions

View file

@ -34,7 +34,7 @@ import java.util.*;
*/ */
public class DataNode implements Iterable<DataNode>{ public class DataNode implements Iterable<DataNode>{
public enum DataType{ public enum DataType{
Map, List, String, Number, Boolean Map, List, String, Number, Boolean, Null
} }
private Map<String,DataNode> map = null; private Map<String,DataNode> map = null;
private List<DataNode> list = null; private List<DataNode> list = null;
@ -249,6 +249,9 @@ public class DataNode implements Iterable<DataNode>{
public boolean isValue(){ public boolean isValue(){
return type != DataType.Map && type != DataType.List; return type != DataType.Map && type != DataType.List;
} }
public boolean isNull(){
return type == DataType.Null;
}
/** /**
* @return the type of the node * @return the type of the node
*/ */

View file

@ -104,6 +104,9 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
} }
protected Object readObject(Class<?> type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException, NoSuchFieldException { protected Object readObject(Class<?> type, String key, DataNode json) throws IllegalAccessException, InstantiationException, ClassNotFoundException, IllegalArgumentException, UnsupportedDataTypeException, NoSuchFieldException {
// Only parse if json is a map
if(!json.isMap())
return null;
// See if the Object id is in the cache before continuing // See if the Object id is in the cache before continuing
if(json.getString("@object_id") != null && objectCache.containsKey(json.getInt(MD_OBJECT_ID))) if(json.getString("@object_id") != null && objectCache.containsKey(json.getInt(MD_OBJECT_ID)))
return objectCache.get(json.getInt(MD_OBJECT_ID)); return objectCache.get(json.getInt(MD_OBJECT_ID));
@ -185,13 +188,20 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
} }
// Field is a new Object // Field is a new Object
else{ else{
Field field = type.getField(key); Field field = getFieldInClass(type, key);
if(field != null) if(field != null)
return readObject(field.getType(), key, json); return readObject(field.getType(), key, json);
else else
return readObject(null, key, json); return readObject(null, key, json);
} }
} }
private Field getFieldInClass(Class<?> c, String name){
for(Field f : c.getFields()){
if(f.getName().equals(name))
return f;
}
return null;
}
protected static Object readPrimitive(Class<?> type, DataNode json){ protected static Object readPrimitive(Class<?> type, DataNode json){
if (type == int.class || if (type == int.class ||

View file

@ -41,14 +41,15 @@ import java.util.Map;
public class JSONObjectOutputStream extends OutputStream implements ObjectOutput, Closeable{ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput, Closeable{
/** If the generated JSON should contain class def meta-data **/ /** If the generated JSON should contain class def meta-data **/
private boolean generateMetaData; private boolean generateMetaData = true;
/** If fields that are null should be included in the json **/
private boolean ignoreNullFields = true;
/** Cache of parsed objects **/ /** Cache of parsed objects **/
private HashMap<Object,Integer> objectCache; private HashMap<Object,Integer> objectCache;
private JSONWriter out; private JSONWriter out;
private JSONObjectOutputStream() { private JSONObjectOutputStream() {
this.generateMetaData = true;
this.objectCache = new HashMap<Object, Integer>(); this.objectCache = new HashMap<Object, Integer>();
} }
public JSONObjectOutputStream(OutputStream out) { public JSONObjectOutputStream(OutputStream out) {
@ -103,18 +104,21 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
if((field.getModifiers() & Modifier.STATIC) == 0 && if((field.getModifiers() & Modifier.STATIC) == 0 &&
(field.getModifiers() & Modifier.TRANSIENT) == 0){ (field.getModifiers() & Modifier.TRANSIENT) == 0){
field.setAccessible(true); field.setAccessible(true);
Object fieldObj = field.get(obj);
// has object a value?
if(ignoreNullFields && fieldObj == null)
continue;
// Add basic type (int, float...) // Add basic type (int, float...)
if(ClassUtil.isPrimitive(field.getType()) || else if(ClassUtil.isPrimitive(field.getType()) ||
ClassUtil.isWrapper(field.getType())){ ClassUtil.isWrapper(field.getType())){
root.set(field.getName(), getPrimitiveDataNode(field.getType(), field.get(obj))); root.set(field.getName(), getPrimitiveDataNode(field.getType(), fieldObj));
} }
// Add an array // Add an array
else if(field.getType().isArray()){ else if(field.getType().isArray()){
DataNode arrayNode = new DataNode(DataNode.DataType.List); DataNode arrayNode = new DataNode(DataNode.DataType.List);
Object array = field.get(obj); for(int i=0; i< Array.getLength(fieldObj) ;i++){
for(int i=0; i< Array.getLength(array) ;i++){ arrayNode.add(getDataNode(Array.get(fieldObj, i)));
arrayNode.add(getDataNode(Array.get(array, i)));
} }
root.set(field.getName(), arrayNode); root.set(field.getName(), arrayNode);
} }
@ -125,7 +129,7 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
// TODO Add Map Support // TODO Add Map Support
} }
else{ else{
root.set(field.getName(), getDataNode(field.get(obj))); root.set(field.getName(), getDataNode(fieldObj));
} }
} }
} }
@ -171,6 +175,14 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
generateMetaData = generate; generateMetaData = generate;
} }
/**
* Defines if null fields in objects should be included
* in the JSON output.
*/
public void ignoreNullFields(boolean enable) {
ignoreNullFields = enable;
}
public void flush() throws IOException { public void flush() throws IOException {
super.flush(); super.flush();
out.flush(); out.flush();

View file

@ -38,11 +38,13 @@ import java.util.regex.Pattern;
* @author Ziver * @author Ziver
*/ */
public class JSONParser extends Parser { public class JSONParser extends Parser {
public static final Pattern NUMBER_PATTERN = Pattern.compile("^[0-9.]++$"); private static final Pattern NUMBER_PATTERN = Pattern.compile("^[0-9.]++$");
public static final Pattern BOOLEAN_PATTERN = Pattern.compile("^(true|false)$", Pattern.CASE_INSENSITIVE); private static final Pattern BOOLEAN_PATTERN = Pattern.compile("^(true|false)$", Pattern.CASE_INSENSITIVE);
private static final Pattern NULL_PATTERN = Pattern.compile("^null$", Pattern.CASE_INSENSITIVE);
private Reader in; private Reader in;
public JSONParser(Reader in){ public JSONParser(Reader in){
this.in = in; this.in = in;
} }
@ -137,7 +139,9 @@ public class JSONParser extends Parser {
} }
// Check what type of type the data is // Check what type of type the data is
String data = tmp.toString().trim(); String data = tmp.toString().trim();
if( BOOLEAN_PATTERN.matcher(data).matches() ) if( NULL_PATTERN.matcher(data).matches() )
root = new DataNode(DataType.Null);
else if( BOOLEAN_PATTERN.matcher(data).matches() )
root = new DataNode(DataType.Boolean); root = new DataNode(DataType.Boolean);
else if( NUMBER_PATTERN.matcher(data).matches() ) else if( NUMBER_PATTERN.matcher(data).matches() )
root = new DataNode(DataType.Number); root = new DataNode(DataType.Number);

View file

@ -23,6 +23,7 @@
*/ */
package zutil.test; package zutil.test;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import zutil.io.StringOutputStream; import zutil.io.StringOutputStream;
import zutil.parser.json.JSONObjectInputStream; import zutil.parser.json.JSONObjectInputStream;
@ -54,8 +55,8 @@ public class JSONSerializerTest{
TestClass sourceObj = new TestClass().init(); TestClass sourceObj = new TestClass().init();
TestClass targetObj = sendReceiveObject(sourceObj); TestClass targetObj = sendReceiveObject(sourceObj);
assertEquals( sourceObj, targetObj ); TestClass.assertEquals(sourceObj, targetObj);
} }
@Test @Test
@ -116,11 +117,11 @@ public class JSONSerializerTest{
String data = writeObjectToJson(sourceObj, false); String data = writeObjectToJson(sourceObj, false);
data = data.replace("\"", "'"); data = data.replace("\"", "'");
assertEquals( assertEquals(
"{'str': null, 'obj1': null, 'obj2': null, 'decimal': 0.0}", "{'decimal': 0.0}",
data); data);
TestClass targetObj = sendReceiveObject(sourceObj); TestClass targetObj = sendReceiveObject(sourceObj);
assertEquals( sourceObj, targetObj ); TestClass.assertEquals(sourceObj, targetObj);
} }
@ -176,12 +177,11 @@ public class JSONSerializerTest{
return this; return this;
} }
public boolean equals(Object obj){ public static void assertEquals(TestClass obj1, TestClass obj2){
return obj instanceof TestClass && Assert.assertEquals(obj1.str, obj2.str);
this.str.equals(((TestClass)obj).str) && Assert.assertEquals(obj1.decimal, obj2.decimal, 0.001);
this.decimal == ((TestClass)obj).decimal && Assert.assertEquals(obj1.obj1, obj2.obj1);
this.obj1.equals(((TestClass)obj).obj1) && Assert.assertEquals(obj1.obj2, obj2.obj2);
this.obj2.equals(((TestClass)obj).obj2);
} }
} }