package lesson06.json;
import lesson06.json.adapters.UseDataAdapter;
import org.json.JSONObject;
import org.json.JSONArray;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* JsonSerializer converts Java objects to JSON representation.
*/
public class JsonSerializer {
/**
* simpleTypes contains java classes for which we should not make any deeper serialization and we should return object as is
* and use toString() method to get it serialized representation
*/
private static Set<Class> simpleTypes = new HashSet<Class>(Arrays.asList(
JSONObject.class,
JSONArray.class,
String.class,
Integer.class,
Short.class,
Long.class,
Byte.class,
Double.class,
Float.class,
Character.class,
Boolean.class,
int.class,
short.class,
long.class,
byte.class,
double.class,
float.class,
char.class,
boolean.class
));
/**
* Main method to convert Java object to JSON. If type of the object is part of the simpleTypes object itself will be returned.
* If object is null String value "null" will be returned.
*
* @param o object to serialize.
* @return JSON representation of the object.
*/
public static Object serialize(Object o) {
if (null == o) {
return "null";
}
if (simpleTypes.contains(o.getClass())) {
return o;
} else {
try {
return toJsonObject(o);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
/**
* Converts Java object to JSON. Uses reflection to access object fields.
* Uses JsonDataAdapter to serialize complex values. Ignores @Ignore annotated fields.
*
* @param o object to serialize to JSON
* @return JSON object.
* @throws IllegalAccessException
* @throws InstantiationException
*/
private static String toJsonObject(Object o) throws Exception {
JSONObject jsonObject = new JSONObject();
Class objectClass = o.getClass();
Field[] fields = objectClass.getDeclaredFields();
for (Field field : fields) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), o.getClass());
field.setAccessible(true);
if (field.isAnnotationPresent(Ignore.class)) {
continue;
} else if (field.isAnnotationPresent(UseDataAdapter.class)) {
UseDataAdapter adapter = field.getAnnotation(UseDataAdapter.class);
jsonObject.put(field.getName(), adapter.value().newInstance().toJson(propertyDescriptor.getReadMethod().invoke(o)));
} else {
jsonObject.put(field.getName(), serialize(propertyDescriptor.getReadMethod().invoke(o)));
}
field.setAccessible(false);
}
return jsonObject.toString(4);
}
}