/*
* Copyright 2015, Yahoo Inc.
* Copyrights licensed under the GPL License.
* See the accompanying LICENSE file for terms.
*/
// function class
// Helps any object encode its member variables as JSON.
// Any JsonAble object can customize its encoding in its own to/fromJson() function
package com.yahoo.egads.data;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Iterator;
import org.json.JSONArray;
import org.json.JSONStringer;
import org.json.JSONObject;
public class JsonEncoder {
// methods ////////////////////////////////////////////////
public static String toJson(Object object) throws Exception {
JSONStringer jsonOut = new JSONStringer();
toJson(object, jsonOut);
return jsonOut.toString();
}
public static void // modifies json_out
toJson(Object object, JSONStringer json_out) throws Exception {
json_out.object();
// for each inherited class...
for (Class c = object.getClass(); c != Object.class; c = c
.getSuperclass()) {
// for each member variable...
Field[] fields = c.getDeclaredFields();
for (Field f : fields) {
// if variable is static/private... skip it
if (Modifier.isStatic(f.getModifiers())) {
continue;
}
if (Modifier.isPrivate(f.getModifiers())) {
continue;
}
Object value = f.get(object);
// if variable is a complex type... recurse on sub-objects
if (value instanceof JsonAble) {
json_out.key(f.getName());
((JsonAble) value).toJson(json_out);
// if variable is an array... recurse on sub-objects
} else if (value instanceof ArrayList) {
json_out.key(f.getName());
json_out.array();
for (Object e : (ArrayList) value) {
toJson(e, json_out);
}
json_out.endArray();
// if variable is a simple type... convert to json
} else {
json_out.key(f.getName()).value(value);
}
}
}
json_out.endObject();
}
public static void fromJson(Object object, String json_str)
throws Exception {
JSONObject jsonObj = new JSONObject(json_str);
fromJson(object, jsonObj);
}
public static void fromJson(Object object, JSONObject json_obj)
throws Exception {
// for each json key-value, that has a corresponding variable in object ...
for (Iterator k = json_obj.keys(); k.hasNext();) {
String key = (String) k.next();
Object value = json_obj.get(key);
// try to access object variable
Field field = null;
try {
field = object.getClass().getField(key);
} catch (Exception e) {
continue;
}
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (Modifier.isPrivate(field.getModifiers())) {
continue;
}
Object member = field.get(object);
if (json_obj.isNull(key)) {
field.set(object, null);
continue;
// if variable is container... recurse
} else if (member instanceof JsonAble) {
((JsonAble) member).fromJson((JSONObject) value);
// if variable is an array... recurse on sub-objects
} else if (member instanceof ArrayList) {
// Depends on existance of ArrayList template parameter, and T constructor with no arguments.
// May be better to use custom fromJson() in member class.
ArrayList memberArray = (ArrayList) member;
JSONArray jsonArray = (JSONArray) value;
// find array element constructor
ParameterizedType arrayType = null;
if (field.getGenericType() instanceof ParameterizedType) {
arrayType = (ParameterizedType) field.getGenericType();
}
for (Class c = member.getClass(); arrayType == null
&& c != null; c = c.getSuperclass()) {
if (c.getGenericSuperclass() instanceof ParameterizedType) {
arrayType = (ParameterizedType) c
.getGenericSuperclass();
}
}
if (arrayType == null) {
throw new Exception(
"could not find ArrayList element type for field 'key'");
}
Class elementClass = (Class) (arrayType
.getActualTypeArguments()[0]);
Constructor elementConstructor = elementClass.getConstructor();
// for each element in JSON array ... append element to member array, recursively decode element
for (int i = 0; i < jsonArray.length(); ++i) {
Object element = elementConstructor.newInstance();
fromJson(element, jsonArray.getJSONObject(i));
memberArray.add(element);
}
// if variable is simple value... set
} else if (field.getType() == float.class) {
field.set(object, (float) json_obj.getDouble(key));
} else {
field.set(object, value);
}
}
}
}
Ads help maintain this website.