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 enum DataType{
Map, List, String, Number, Boolean
Map, List, String, Number, Boolean, Null
}
private Map<String,DataNode> map = null;
private List<DataNode> list = null;
@ -249,6 +249,9 @@ public class DataNode implements Iterable<DataNode>{
public boolean isValue(){
return type != DataType.Map && type != DataType.List;
}
public boolean isNull(){
return type == DataType.Null;
}
/**
* @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 {
// Only parse if json is a map
if(!json.isMap())
return null;
// 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));
@ -185,13 +188,20 @@ public class JSONObjectInputStream extends InputStream implements ObjectInput, C
}
// Field is a new Object
else{
Field field = type.getField(key);
Field field = getFieldInClass(type, key);
if(field != null)
return readObject(field.getType(), key, json);
else
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){
if (type == int.class ||

View file

@ -41,14 +41,15 @@ import java.util.Map;
public class JSONObjectOutputStream extends OutputStream implements ObjectOutput, Closeable{
/** 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 **/
private HashMap<Object,Integer> objectCache;
private JSONWriter out;
private JSONObjectOutputStream() {
this.generateMetaData = true;
this.objectCache = new HashMap<Object, Integer>();
}
public JSONObjectOutputStream(OutputStream out) {
@ -103,18 +104,21 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
if((field.getModifiers() & Modifier.STATIC) == 0 &&
(field.getModifiers() & Modifier.TRANSIENT) == 0){
field.setAccessible(true);
Object fieldObj = field.get(obj);
// has object a value?
if(ignoreNullFields && fieldObj == null)
continue;
// Add basic type (int, float...)
if(ClassUtil.isPrimitive(field.getType()) ||
else if(ClassUtil.isPrimitive(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
else if(field.getType().isArray()){
DataNode arrayNode = new DataNode(DataNode.DataType.List);
Object array = field.get(obj);
for(int i=0; i< Array.getLength(array) ;i++){
arrayNode.add(getDataNode(Array.get(array, i)));
for(int i=0; i< Array.getLength(fieldObj) ;i++){
arrayNode.add(getDataNode(Array.get(fieldObj, i)));
}
root.set(field.getName(), arrayNode);
}
@ -125,7 +129,7 @@ public class JSONObjectOutputStream extends OutputStream implements ObjectOutput
// TODO Add Map Support
}
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;
}
/**
* 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 {
super.flush();
out.flush();

View file

@ -38,11 +38,13 @@ import java.util.regex.Pattern;
* @author Ziver
*/
public class JSONParser extends Parser {
public 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 NUMBER_PATTERN = Pattern.compile("^[0-9.]++$");
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;
public JSONParser(Reader in){
this.in = in;
}
@ -137,7 +139,9 @@ public class JSONParser extends Parser {
}
// Check what type of type the data is
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);
else if( NUMBER_PATTERN.matcher(data).matches() )
root = new DataNode(DataType.Number);

View file

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