Fixed null field issues in JSON
This commit is contained in:
parent
0bb193fba3
commit
051f6fdcf8
5 changed files with 52 additions and 23 deletions
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue