package io.client.thrift;
import static java.lang.reflect.Modifier.ABSTRACT;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
/**
* JSON 序列化和反序列化工具类
*
* @author HouKangxi
*
*/
public class Json {
// 系统ClassLoader, 一般是null, 取决于vm 实现
private static final ClassLoader ROOT_CLASSLOADER = Object.class.getClassLoader();
/**
* JSON序列(和反序列)化策略
*/
public static class Strategy {
int excludeModifiers = Modifier.TRANSIENT | Modifier.STATIC;
/**
* 返回字段名,如果返回null,则表示忽略这个字段
*
* @param field
* @return
*/
public String fieldName(Field field) {
if (excludeClass(field.getType(), true))
return null;
return field.getName();
}
public Field field(Class<?> cls, String fieldName) throws NoSuchFieldException, SecurityException {
if (excludeClass(cls, false))
return null;
Field f = cls.getDeclaredField(fieldName);
if ((f.getModifiers() & excludeModifiers) != 0) {
return null;
}
f.setAccessible(true);
return f;
}
/**
* 是否忽略指定class
*
* @param clazz
* @param serialize
* - 是否在序列化过程中(Object to JSON)
* @return
*/
public boolean excludeClass(Class<?> clazz, boolean serialize) {
return false;
}
public void excludeFieldsWithModifiers(int... modifiers) {
excludeModifiers = 0;
for (int modifier : modifiers) {
excludeModifiers |= modifier;
}
}
public void publicFieldsOnly() {
excludeFieldsWithModifiers(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.STATIC, Modifier.TRANSIENT);
}
}
public static <T> T fromJson(String json, Type type) throws Exception {
return fromJson(json, type, new Strategy());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> T fromJson(String json, Type type, Strategy strategy) throws Exception {
if (type instanceof Class) {
Class cls = (Class) type;
if (strategy.excludeClass(cls, false))
return null;
if (cls.isArray()) {
JSONArray arr = new JSONArray(json);
Class et = cls.getComponentType();
Object a = Array.newInstance(et, arr.length());
for (int i = 0; i < arr.length(); i++) {
Array.set(a, i, fromJson(toJson(et, arr.get(i), strategy), et, strategy));
}
return (T) a;
} else if (cls.getClassLoader() == ROOT_CLASSLOADER) {
JSONTokener tk = new JSONTokener(json);
return (T) tk.nextValue();
} else {// 自定义类型
JSONObject jo = new JSONObject(json);
Iterator keys = jo.keys();
Object map = cls.newInstance();
while (keys.hasNext()) {
String k = (String) keys.next();
try {
Field f = strategy.field(cls, k);
if (f != null) {
Type vt = f.getGenericType();
Object ov = fromJson(toJson(vt, jo.get(k), strategy), vt, strategy);
f.set(map, ov);
}
} catch (NoSuchFieldException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
return (T) map;
}
} else if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Class cls = (Class) pt.getRawType();
if (List.class.isAssignableFrom(cls)) {
JSONArray arr = new JSONArray(json);
Type et = pt.getActualTypeArguments()[0];
List list = (cls.getModifiers() & ABSTRACT) != 0 ? new ArrayList(arr.length())
: ((List) cls.newInstance());
for (int i = 0; i < arr.length(); i++) {
Object ov = fromJson(toJson(et, arr.get(i), strategy), et, strategy);
list.add(ov);
}
return (T) list;
} else if (Set.class.isAssignableFrom(cls)) {
JSONArray arr = new JSONArray(json);
Type et = pt.getActualTypeArguments()[0];
Set set = (cls.getModifiers() & ABSTRACT) != 0 ? new HashSet(arr.length()) : ((Set) cls.newInstance());
for (int i = 0; i < arr.length(); i++) {
Object ov = fromJson(toJson(et, arr.get(i), strategy), et, strategy);
set.add(ov);
}
return (T) set;
} else if (Map.class.isAssignableFrom(cls)) {
JSONObject jo = new JSONObject(json);
Map map = (cls.getModifiers() & ABSTRACT) != 0 ? new HashMap(jo.length()) : ((Map) cls.newInstance());
// Type kt = pt.getActualTypeArguments()[0];
Type vt = pt.getActualTypeArguments()[1];
Iterator keys = jo.keys();
while (keys.hasNext()) {
Object k = keys.next();
Object ov = fromJson(toJson(vt, jo.get(String.valueOf(k)), strategy), vt, strategy);
map.put(k, ov);
}
return (T) map;
}
}
return null;
}
public static String toJson(Object obj) {
if (obj == null) {
return "null";
}
return toJson(obj, new Strategy());
}
public static String toJson(Object obj, Strategy strategy) {
if (obj == null) {
return "null";
}
return toJson(obj.getClass(), obj, strategy);
}
public static String toJson(Type oType, Object obj, Strategy strategy) {
if (obj == null) {
return "null";
}
StringBuilder sb = new StringBuilder(256);
toJson(oType, obj, sb, strategy);
return sb.toString();
}
@SuppressWarnings("rawtypes")
public static void toJson(Type oType, Object obj, StringBuilder sb, Strategy strategy) {
if (obj == null) {
sb.append(JSONObject.NULL);
return;
}
if (obj instanceof JSONObject || obj instanceof JSONArray) {
sb.append(obj);
return;
}
Class clazz = obj.getClass();
if (oType instanceof Class) {
Class cls = (Class) oType;
if (strategy.excludeClass(cls, true))
return;
if (obj instanceof CharSequence) {
sb.append('"').append(obj).append('"');
} else if (clazz.isArray()) {
sb.append('[');
Class et = clazz.getComponentType();
for (int i = 0, len = Array.getLength(obj); i < len; i++) {
Object oe = Array.get(obj, i);
toJson(oe != null ? oe.getClass() : et, oe, sb, strategy);
sb.append(',');
}
if (sb.charAt(sb.length() - 1) == ',')
sb.deleteCharAt(sb.length() - 1);
sb.append(']');
} else if (cls.getClassLoader() == ROOT_CLASSLOADER) {
sb.append(obj);
} else {
// 用户自定义的类型
Field[] fs = clazz.getDeclaredFields();
sb.append('{');
for (Field f : fs) {
if ((f.getModifiers() & strategy.excludeModifiers) != 0)
continue;
String fname = strategy.fieldName(f);
if (fname == null)
continue;
try {
f.setAccessible(true);
Object v = f.get(obj);
if (v != null) {
sb.append('"').append(fname).append('"').append(':');
toJson(f.getGenericType(), v, sb, strategy);
sb.append(',');
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (sb.charAt(sb.length() - 1) == ',')
sb.deleteCharAt(sb.length() - 1);
sb.append('}');
}
} else {
if (obj instanceof Collection) {
sb.append('[');
Collection col = (Collection) obj;
Type eType = null;
if (oType instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) oType;
eType = ptype.getActualTypeArguments()[0];
}
for (Object o : col) {
toJson(eType, o, sb, strategy);
sb.append(',');
}
if (sb.charAt(sb.length() - 1) == ',')
sb.deleteCharAt(sb.length() - 1);
sb.append(']');
} else if (obj instanceof Map) {
sb.append('{');
Map<?, ?> m = (Map) obj;
Type vType = null;
if (oType instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType) oType;
vType = ptype.getActualTypeArguments()[1];
}
for (Map.Entry e : m.entrySet()) {
sb.append('"').append(e.getKey()).append('"').append(':');
Object ev = e.getValue();
toJson(vType, ev, sb, strategy);
sb.append(',');
}
if (sb.charAt(sb.length() - 1) == ',')
sb.deleteCharAt(sb.length() - 1);
sb.append('}');
} else {
sb.append(obj);
}
}
}
}