package com.tangyu.component.util; import android.text.TextUtils; import com.alibaba.fastjson.JSON; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.util.LinkedList; import java.util.List; /** * This class depends on 'Fastjson'. * Support a simple way to translate between Object and JsonObject. * Like this: * <pre> * // java bean is follow the rule of FastJson. * class A implements IJsonBeanV2 { * private int paramA; * private String paramB; * * // sets/gets ... * * public static final EncodeObjectV2<A> CODE = new EncodeObjectV2<A>() { }; * public static final EncodeString<A> CODE_STRING = new EncodeString<A>() { }; * } * * // invoking. * // encode object to jsonObject * A.CODE.encode(...); * // decode jsonObject to object * A.CODE.decode(...); * // encode object to String * A.CODE_STRING.encode(...); * // decode String to object * A.CODE_STRING.decode(...); * * </pre> * * @see com.tangyu.component.demo.util.JavaBeanV2 * * @author binliu on 8/24/14. */ public interface IJsonBeanV2 { public static final EncodeObject CODE = null; public static final EncodeArray CODE_ARRAY = null; public static final EncodeString CODE_STRING = null; public static final EncodeStrings CODE_STRING_ARRAY = new EncodeStrings(); public static interface IEncode<T, E> { public E encode(T instance); public T decode(E jsonObject); } public static interface EncodeArray<T> extends IEncode<T, JSONArray> { public JSONArray encode(T instance); public T decode(JSONArray jsonArray); } public static interface EncodeWithString<T> extends IEncode<T, String> { } /** * List<String> to JsonArray */ public static final class EncodeStrings implements IJsonBeanV2.EncodeArray<List<String>> { @Override public JSONArray encode(List<String> instance) { JSONArray jsonArray = new JSONArray(); if (null != instance) { for (String item : instance) { if (null != item) jsonArray.put(item); } } return jsonArray; } @Override public List<String> decode(JSONArray jsonArray) { LinkedList<String> result = new LinkedList<String>(); if (null != jsonArray) { for (int i = 0; i < jsonArray.length(); ++i) { String item = jsonArray.optString(i); if (null != item) result.add(item); } } return result; } } /** * String <--> JsonObject */ public static abstract class EncodeString<T> implements EncodeWithString<T> { Class<T> entityClass; protected Class<T> getGenericClass() { return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } @Override public T decode(String instance) { if (entityClass == null) { entityClass = getGenericClass(); } if (TextUtils.isEmpty(instance) || 0 == TextUtils.getTrimmedLength(instance)) { return null; } return JSON.parseObject(instance, entityClass); } @Override public String encode(T object) { if (object == null) return null; return JSON.toJSONString(object); } } /** * Object <--> JsonObject * Logic is same as {@link IJsonBeanV2.EncodeString} * @param <T> */ public static abstract class EncodeObject<T> implements IEncode<T, JSONObject> { Class<T> entityClass; protected Class<T> getGenericClassIfNeed() { return null == entityClass ? entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0] : entityClass; } @Override public JSONObject encode(T instance) { Class<T> genericClassIfNeed = getGenericClassIfNeed(); try { Field field = genericClassIfNeed.getDeclaredField("CODE_STRING"); Method encodeMethod = field.getType().getDeclaredMethod("encode", Object.class); String string = (String) encodeMethod.invoke(field.get(null), instance); return new JSONObject(string); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return new JSONObject(); } @Override public T decode(JSONObject jsonObject) { Class<T> genericClassIfNeed = getGenericClassIfNeed(); try { Field field = genericClassIfNeed.getDeclaredField("CODE_STRING"); Method encodeMethod = field.getType().getDeclaredMethod("decode", String.class); return (T) encodeMethod.invoke(field.get(null), jsonObject.toString()); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return null; } } }