package com.jiuqi.lbsinterface.json;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import com.jiuqi.lbsinterface.utils.Base64;
import com.jiuqi.lbsinterface.utils.Base64DecodingException;
import com.jiuqi.lbsinterface.ws.WSConsts;
public class JSONConvertor {
private static <T> boolean isWrapClass(Class<T> clazs){
if(clazs == String.class||
clazs == Integer.class||
clazs == Long.class||
clazs == Double.class||
clazs == Short.class||
clazs == Character.class||
clazs == Boolean.class||
clazs == Float.class||
clazs == Byte.class
)return true;
return false;
}
private static <T> boolean isWrapClass(Object clazs){
return isWrapClass(clazs.getClass());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Object serializable(Object t){
if(t==null)return null;
if(isWrapClass(t))return t;
if(t.getClass().isEnum())return t;
JSONObject result = new JSONObject();
try{
result.put(WSConsts.CLASS_TAG, t.getClass().getName());
}
catch(JSONException e1){
e1.printStackTrace();
}
Class clazs = t.getClass();
List<Field> fields = getFields(clazs);
for(Field field : fields){
field.setAccessible(true);
Object value = null;
try{
value = field.get(t);
}
catch(IllegalAccessException e){
e.printStackTrace();
throw new RuntimeException("通过反射访问"+field+"属性时发生错误", e);
}
if(field.getType().isPrimitive()||value instanceof String){
try{
result.put(field.getName(), value);
}
catch(JSONException e){
throw new IllegalArgumentException("JSON赋值时发生错误", e);
}
}else if(field.getType() == UUID.class) {
if (value != null) {
UUID uuid = (UUID)value;
long[] bitsArray = new long[]{uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()};
try {
JSONArray uuidObject = new JSONArray(bitsArray);
result.put(field.getName(), uuidObject);
} catch (JSONException e) {
throw new IllegalArgumentException("JSON赋值时发生错误." + e.getMessage(), e);
}
}
}else if(field.getType().isEnum()){
try{
result.put(field.getName(), value);
}
catch(JSONException e){
throw new IllegalArgumentException("JSON赋值时发生错误", e);
}
}else if(field.getType().isSynthetic()||field.getType().isMemberClass()||field.getType().isLocalClass()){
try{
result.put(field.getName(), serializable(value));
}
catch(JSONException e){
throw new IllegalArgumentException("JSON赋值时发生错误", e);
}
}else if(field.getType().isArray()){
try{
Class clazss = field.getType().getComponentType();
if(clazss.isPrimitive()||isWrapClass(clazss)){
if (clazss == byte.class) {
byte[] barray = (byte[]) value;
String base64 = Base64.encode(barray);
result.put(field.getName(), base64);
} else {
if(value != null) {
result.put(field.getName(), new JSONArray(value));
}
}
}else{
Object[] ary = (Object[])value;
JSONArray jsonArray = new JSONArray();
if(ary!=null){
for(Object object : ary){
jsonArray.put(serializable(object));
}
}
result.put(field.getName(), jsonArray);
}
}
catch(JSONException e){
throw new IllegalArgumentException("JSON赋值时发生错误", e);
}
}else if (field.getType()==Date.class) {
if (value != null) {
try {
result.put(field.getName(), ((Date)value).getTime());
} catch (JSONException e) {
throw new IllegalArgumentException("JSON Date类型赋值时发生错误", e);
}
}
}else {
try{
result.put(field.getName(), serializable(value));
}
catch(JSONException e){
throw new IllegalArgumentException("JSON赋值时发生错误", e);
}
}
}
return result;
}
public static <T> T unSerializable(Class<T> t,String arg){
try{
return unSerializable(t, new JSONObject(arg));
}
catch(JSONException e){
throw new IllegalArgumentException("传入的字符串不是一个正确的JSON格式,请检查格式是否正确"+arg.toString());
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public static <T> T unSerializable(Class<T> t,Object arg){
if(arg==null)return null;
if(isWrapClass(t)){
return arg==null ? null : (T)arg;
}
if(t.isEnum()){
for(T e:t.getEnumConstants()){
if(((Enum)e).name().equals(arg)){
return e;
}
}
return null;
}
if(t.isPrimitive()){
return (T)arg;
}
if(t.isArray()){
Class<?> componentType = t.getComponentType();
if (componentType == byte.class && arg instanceof String) {
String base64 = (String)arg;
try {
return (T) Base64.decode(base64);
} catch (Base64DecodingException e) {
return null;
}
}else {
JSONArray array = (JSONArray)arg;
if(array.length()==0)return null;
if (componentType == byte.class) {
/**
* 为兼容2012-12-03之前的上传数据,
* 正式发版时可以去掉
*/
byte[] byteArray = new byte[array.length()];
try {
for(int i=0; i<array.length() ;i++){
byteArray[i] = (byte)array.getInt(i);
}
return (T) byteArray;
} catch (JSONException e) {
e.printStackTrace();
throw new IllegalArgumentException("JSON取值时发生错误"+array, e);
}
} else {
if(componentType.equals(Object.class)){
try{
JSONObject jo = array.getJSONObject(0);
String c = jo.getString("class");
componentType = Class.forName(c, true, Thread.currentThread().getContextClassLoader());
}catch(Exception e){
try {
Object jo = array.get(0);
componentType = jo.getClass();
} catch (JSONException e1) {
}
}
}
T objs = (T)Array.newInstance(componentType, array.length());
for(int i=0;i<array.length();i++){
try{
Object val = null;
if (componentType ==Long.class) {
val = array.getLong(i);
} else {
val = array.get(i);
}
Array.set(objs,i,unSerializable(componentType, val));
}
catch(JSONException e){
e.printStackTrace();
throw new IllegalArgumentException("JSON取值时发生错误"+array, e);
}
}
return objs;
}
}
}
if(t == UUID.class) {
JSONArray uuidObject = (JSONArray)arg;
UUID uuid;
try {
uuid = new UUID(uuidObject.getLong(0), uuidObject.getLong(1));
} catch (JSONException e) {
e.printStackTrace();
throw new IllegalArgumentException("JSON取值时发生错误." + uuidObject, e);
}
return (T) uuid;
}
if (t == Date.class) {
long time = (Long)arg;
return (T)new Date(time);
}
return unSerializable(t, (JSONObject)arg);
}
private static <T> List<Field> getFields(Class<T> t){
List<Field> list = new ArrayList<Field>();
for(Field field : t.getDeclaredFields()){
boolean isSerializable = isSerializable(field);
if(isSerializable)continue;
list.add(field);
}
if(t.getSuperclass()!=Object.class){
list.addAll(getFields(t.getSuperclass()));
}
return list;
}
private static boolean isSerializable(Field field) {
if (Modifier.isStatic(field.getModifiers()))
return false;
Miss miss = field.getAnnotation(Miss.class);
boolean isMiss = false;
if(miss!=null){
isMiss = miss.value();
}
return isMiss;
}
/**
* 将json类型转换成指定的类
*
* @param <T>
* @param t
* @param arg
* @return T
*/
public static <T> T unSerializable(Class<T> t,JSONObject arg){
if(arg==null)return null;
try{
T obj = createNewInstance(t);
for(Field field : getFields(t)){
try{
if(Modifier.isFinal(field.getModifiers()))continue;
String fieldName = field.getName();
if(!arg.has(fieldName))continue;
Object fieldValue = arg.get(fieldName);
if(fieldValue==null)continue;
field.setAccessible(true);
field.set(obj, unSerializable(field.getType(), fieldValue));
}
catch(IllegalAccessException e){
throw new RuntimeException("使用反射机制访问" + t.getName()
+ "类的字段时发生错误:"+field.getName(), e);
}
catch(SecurityException e){
throw new RuntimeException("对类"+t.getName()+"进行反射操作时发生安全异常:"+field.getName(),e);
}
catch(IllegalArgumentException e){
throw new RuntimeException("使用反射机制访问" + t.getName()
+ "类的字段时发生错误"+field.getName(), e);
}
catch(JSONException e){
throw new IllegalArgumentException("传入的JSON参数不正确,请检查格式是否正确,或者字段名是否缺失"+arg.toString(),e);
}
}
return obj;
}
catch(InstantiationException e){
throw new RuntimeException("类" + t.getName()
+ "需要提供一个无参public的构造函数,并且不能是抽象类或者接口或者数组", e);
}
catch(IllegalAccessException e){
throw new RuntimeException("使用反射机制访问" + t.getName()
+ "类的字段时发生错误", e);
}
}
private static <T> T createNewInstance(Class<T> t)
throws InstantiationException, IllegalAccessException {
try {
Constructor<T> constructor = t.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
} catch (SecurityException e1) {
throw new RuntimeException(String.format("不能通过反射访问类型 %s及其无参构造函数",t.getName()));
} catch (NoSuchMethodException e1) {
throw new RuntimeException(String.format("类型%s必须有个无参构造函数",t.getName()));
} catch (IllegalArgumentException e) {
throw new RuntimeException(String.format("调用类型%s的无参构造函数失败", t.getName()));
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
throw new RuntimeException(String.format("调用类型%s的无参构造函数失败,%s",
t.getName(),cause==null?"":cause.getMessage()));
}
}
}