package cn.mutils.core.json;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import cn.mutils.core.beans.BeanField;
import cn.mutils.core.reflect.ReflectUtil;
/**
* JSON serializer of framework.<br>
* Reflection:int->Integer.TYPE Integer->Integer.class
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class JsonUtil {
public static <T> T fromJson(Object json, Class<T> targetClass) throws Exception {
return fromJson(json, targetClass, null);
}
protected static <T> T fromJson(Object json, Class<T> targetClass, Type genericType) throws Exception {
if (JSONObject.NULL.equals(json)) {
return null;
}
if (targetClass == String.class) {
return (T) ((json instanceof String) ? json : json.toString());
} else if (targetClass == Integer.TYPE || targetClass == Integer.class) {
return (T) ((json instanceof Integer) ? json : Integer.valueOf(json.toString()));
} else if (targetClass == Long.TYPE || targetClass == Long.class) {
return (T) ((json instanceof Long) ? json : Long.valueOf(json.toString()));
} else if (targetClass == Double.TYPE || targetClass == Double.class) {
return (T) ((json instanceof Double) ? json : Double.valueOf(json.toString()));
} else if (targetClass == Boolean.TYPE || targetClass == Boolean.class) {
return (T) ((json instanceof Boolean) ? json : Boolean.valueOf(json.toString()));
} else if (Enum.class.isAssignableFrom(targetClass)) {
return (T) ReflectUtil.valueOfEnum(targetClass, (json instanceof String) ? (String) json : json.toString());
} else if (targetClass == JSONObject.class || targetClass == JSONArray.class) {
return (T) json;
}
return fromJson(json, targetClass.newInstance(), genericType);
}
public static <T> T fromJson(Object json, T target) throws Exception {
return fromJson(json, target, null);
}
protected static <T> T fromJson(Object json, T target, Type genericType) throws Exception {
if (JSONObject.NULL.equals(json)) {
return null;
}
if (target instanceof String) {
return (T) ((json instanceof String) ? json : json.toString());
} else if (target instanceof Integer) {
return (T) ((json instanceof Integer) ? json : Integer.valueOf(json.toString()));
} else if (target instanceof Long) {
return (T) ((json instanceof Long) ? json : Long.valueOf(json.toString()));
} else if (target instanceof Double) {
return (T) ((json instanceof Double) ? json : Double.valueOf(json.toString()));
} else if (target instanceof Boolean) {
return (T) ((json instanceof Boolean) ? json : Boolean.valueOf(json.toString()));
} else if (target instanceof Enum) {
return (T) ReflectUtil.valueOfEnum(target.getClass(),
(json instanceof String) ? (String) json : json.toString());
} else if (target instanceof JSONObject || target instanceof JSONArray) {
return (T) json;
} else if (target instanceof Collection) {
return (T) convertCollectionFromJson(json, (Collection<?>) target, genericType);
} else if (target instanceof Map) {
return (T) convertMapFromJson(json, (Map<?, ?>) target, genericType);
} else if (target instanceof IJsonItem) {
return (T) ((IJsonItem) target).fromJson(json, null);
}
JSONObject jsonObject = (JSONObject) json;
for (BeanField f : BeanField.getFields(target.getClass())) {
Object sub = jsonObject.opt(f.getName());
if (sub == null) {
continue;
}
Class<?> fClass = f.getRawType(genericType);
f.set(target,
IJsonItem.class.isAssignableFrom(fClass) ? (((IJsonItem) fClass.newInstance()).fromJson(sub, f))
: fromJson(sub, fClass, f.getGenericType(genericType)));
}
return target;
}
protected static <T extends Collection> T convertCollectionFromJson(Object json, T target, Type genericType)
throws Exception {
Class<?> targetClass = target.getClass();
Class<?> eClass = ReflectUtil.getCollectionElementRawType(targetClass, genericType);
Type eType = ReflectUtil.getCollectionElementGenericType(targetClass, genericType);
JSONArray jsonArray = (JSONArray) json;
for (int i = 0, size = jsonArray.length(); i < size; i++) {
target.add(fromJson(jsonArray.opt(i), eClass, eType));
}
return target;
}
protected static <T extends Map> T convertMapFromJson(Object json, T target, Type genericType) throws Exception {
Class<? extends Map> targetClass = target.getClass();
Class<?> keyClass = ReflectUtil.getMapKeyRawType(targetClass, genericType);
if (!String.class.isAssignableFrom(keyClass)) {
throw new Exception();
}
Class<?> vClass = ReflectUtil.getMapValueRawType(targetClass, genericType);
Type vType = ReflectUtil.getMapValueGenericType(targetClass, genericType);
JSONObject jsonObject = (JSONObject) json;
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext()) {
String k = keys.next();
target.put(k, fromJson(jsonObject.opt(k), vClass, vType));
}
return target;
}
public static <T> T fromString(String str, Class<T> targetClass) throws Exception {
return fromString(str, targetClass, null);
}
public static <T> T fromString(String str, Class<T> targetClass, Type genericType) throws Exception {
if (str == null) {
return null;
}
if (targetClass == String.class) {
return (T) str;
}
return fromJson(fromString(str), targetClass, genericType);
}
public static <T> T fromString(String str, T target) throws Exception {
if (target instanceof String) {
return (T) str;
}
return fromJson(fromString(str), target, null);
}
public static <T> String toString(T target) throws Exception {
if (target == null) {
return null;
}
return toJson(target).toString();
}
public static <T> Object toJson(T target) throws Exception {
if (target == null) {
return JSONObject.NULL;
} else if (target instanceof Collection) {
return convertCollectionToJson(target);
} else if (target instanceof Map) {
return convertMapToJson(target);
} else if (target instanceof IJsonItem) {
return ((IJsonItem) target).toJson(null);
} else if (target instanceof JSONObject) {
return target;
} else if (target instanceof JSONArray) {
return target;
} else if (target instanceof String) {
return target;
} else if (target instanceof Integer) {
return target;
} else if (target instanceof Long) {
return target;
} else if (target instanceof Double) {
return target;
} else if (target instanceof Boolean) {
return target;
} else if (target instanceof Enum) {
return target.toString();
}
JSONObject json = new JSONObject();
for (BeanField f : BeanField.getFields(target.getClass())) {
Object v = f.get(target);
if (v == null) {
continue;
}
json.put(f.getName(), (v instanceof IJsonItem) ? (((IJsonItem) v).toJson(f)) : toJson(v));
}
return json;
}
protected static <T> Object convertCollectionToJson(T target) throws Exception {
JSONArray json = new JSONArray();
for (Object e : (Collection<?>) target) {
json.put(toJson(e));
}
return json;
}
protected static <T> Object convertMapToJson(T target) throws Exception {
JSONObject json = new JSONObject();
for (Entry<?, ?> entry : ((Map<?, ?>) target).entrySet()) {
Object k = entry.getKey();
if (!(k instanceof String)) {
break;
}
Object v = entry.getValue();
if (v == null) {
continue;
}
json.put((String) k, toJson(v));
}
return json;
}
public static Object fromString(String json) throws Exception {
return new JSONTokener(json).nextValue();
}
}