Java tutorial
/* * Copyright (C) 2013 'Chaos'.Personal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.rejuvenation.parse.json; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Queue; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; import com.rejuvenation.parse.json.annotation.JFields; import com.rejuvenation.reflect.ReflectUtils; import com.rejuvenation.utils.RLog; /** * the json property * * @author Chaos * @date 2013-5-30 */ public class JProperty { private static final String l = "<"; private static final String r = ">"; private Set<JFieldBean> mFieldSet; private Object mObj = null; /** * Queue notice: * HashMap<List<HashMap<String,Integer>,HashMap<Object,String>> * Queue? first --> List,HashMap,String,Integer then --> * HashMap,Object,String ,??AddQueue. */ private Queue<Class<?>> mGenericQueue = null; private JProperty(String json, Class<?> target) { init(); RLog.D.p("init ok"); readObject(ReflectUtils.newObjectSilent(target)); RLog.D.p("readObject ok"); } private JProperty(Object obj) { init(); RLog.D.p("init ok"); readObject(obj); RLog.D.p("readObject ok"); } private void init() { mFieldSet = new HashSet<JFieldBean>(); mGenericQueue = new LinkedBlockingQueue<Class<?>>(); } /** * Class?Set */ private void readObject(Object obj) { mObj = obj; // step.1: ?target?? Field[] fiedls = obj.getClass().getDeclaredFields(); // step.2: ??field?,Set for (int i = 0; i < fiedls.length; i++) { Field field = fiedls[i]; // step.2-1: JFieldBean JFieldBean bean = new JFieldBean(field); // step.2-2: init bean // set field name bean.setFieldName(field.getName()); // set field json name JFields jField = field.getAnnotation(JFields.class); if (jField != null) { bean.setJsonFieldName(jField.name()); } mFieldSet.add(bean); } } // ------ build ------- public static String build(Object obj) { return new JProperty(obj).buildJson().toString(); } public static JSONObject buildJsonObject(Object obj) { return new JProperty(obj).buildJson(); } private JSONObject buildJson() { RLog.D.p("build json string..."); JSONObject object = new JSONObject(); for (JFieldBean bean : mFieldSet) { putObjectSilently(object, bean.getJsonFieldName(), ReflectUtils.getValue(mObj, bean.getField())); } RLog.D.p("build json string end..." + object.toString()); return object; } private void putObjectSilently(JSONObject obj, String key, Object value) { try { RLog.D.p("putObjectSilently..."); obj.put(key, getVeriestJson(value)); } catch (JSONException e) { throw new RuntimeException(e); } } private Object getVeriestJson(Object value) throws JSONException { RLog.D.p("getVeriestJson -> " + value.getClass().getSimpleName()); if (value instanceof Map) { RLog.D.p("isMap"); return mapToJson((Map<?, ?>) value); } else if (value instanceof List) { RLog.D.p("isList"); return listToJson((List<?>) value); } else if (value instanceof Set) { RLog.D.p("isSet"); return setToJson((Set<?>) value); } else if (value instanceof JsonBean) { RLog.D.p("isOtherBean"); return JProperty.buildJsonObject(value); } else { RLog.D.p("isCommon"); return value; } } private JSONObject mapToJson(Map<?, ?> map) throws JSONException { JSONObject jobj = new JSONObject(); for (@SuppressWarnings("rawtypes") Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) { Entry<?, ?> entry = (Entry<?, ?>) iterator.next(); jobj.put(entry.getKey().toString(), getVeriestJson(entry.getValue())); } return jobj; } private JSONArray listToJson(List<?> list) throws JSONException { JSONArray jarray = new JSONArray(); for (Object object : list) { jarray.put(getVeriestJson(object)); } return jarray; } private JSONArray setToJson(Set<?> set) throws JSONException { JSONArray jarray = new JSONArray(); for (Object object : set) { jarray.put(getVeriestJson(object)); } return jarray; } // ------ reverseBuild ------ public static <T> T toBean(String json, Class<? extends T> target) { return reverseBuild(json, target); } @SuppressWarnings("unchecked") public static <T> T reverseBuild(String json, Class<? extends T> target) { RLog.D.p("start -> reverseBuild"); return (T) new JProperty(json, target).parseToClass(json); } private Object parseToClass(String json) { RLog.D.p("parseToClass..."); JSONObject obj = getJsonObjectSilently(json); for (JFieldBean bean : mFieldSet) { ReflectUtils.setValue(mObj, bean.getFieldName(), getObjectSilently(obj, bean.getJsonFieldName(), bean)); } return mObj; } private JSONObject getJsonObjectSilently(String json) { try { return new JSONObject(new JSONTokener(json)); } catch (JSONException e) { throw new RuntimeException(e); } } private Object getObjectSilently(JSONObject obj, String key, JFieldBean bean) { try { RLog.D.p("getObjectSilently --> the field : " + bean.getFieldName()); loadGenericIfNeed(bean); return getVeriest(obj.get(key), bean.getType()); } catch (JSONException e) { throw new RuntimeException(e); } } private void loadGenericIfNeed(JFieldBean bean) { RLog.D.p("loadGenericIfNeed() --->"); // first, clear the 'queue', maybe no meaning. mGenericQueue.clear(); // parse the generic and add the queue String[] generics = ReflectUtils.getGenericStr(bean.getField()); // no generic if (generics == null) { RLog.D.p("the field is " + bean.getFieldName() + " it's no generic"); return; } else { RLog.D.p("get generics complete , count is " + generics.length); for (int i = 0; i < generics.length; i++) { RLog.D.p("the " + (i + 1) + " is : " + generics[i]); } for (String generic : generics) { parseGenerice(generic, mGenericQueue); } } } private void parseGenerice(String str, Queue<Class<?>> queue) { RLog.D.p("parseGenerice() --->"); // prototype ArrayList<HashMap<ArrayList<String>,Phone>> // like this : java.util.HashMap<java.util.ArrayList<java.lang.String>, // com.rejuvenation.database.Phone> // fix unknown bug at 2013-06-08... // i don't know why it maybe contains 'class' at the front if (str.contains("class")) { str = str.replaceAll("class", ""); } List<String> list = parseStr(str); for (String string : list) { RLog.D.p("try to get the class >" + string + "<"); mGenericQueue.add(ReflectUtils.getClassSliently(string)); } } private List<String> parseStr(String str) { RLog.D.p("parseStr(): >" + str + "<"); // the result ArrayList<String> list = new ArrayList<String>(); if (!str.contains(l) && !str.contains(r)) { list.add(clear(str)); return list; } String[] left = str.split(l); int leftLength = left.length; String[] right = left[leftLength - 1].split(r); RLog.D.p("the left count is : " + left.length + " the right count it : " + right.length); for (String l : left) { RLog.D.p("left " + l); handleComma(l, list); } for (String r : right) { RLog.D.p("right " + r); handleComma(r, list); } return list; } private void handleComma(String str, List<String> list) { if (str.contains(", ")) { String[] commas = str.split(", "); for (String comma : commas) { list.add(clear(comma)); } } else { list.add(clear(str)); } } private String clear(String str) { // fix unknown bug at 2013-06-08... // i don't know why it maybe contains ">" at the last... if (str.endsWith(r)) { str = str.substring(0, str.length() - 1); } return str.trim(); } private Object getVeriest(Object json, Class<?> type) throws JSONException { if (type == null) { RLog.D.p("getVeriest -> " + "type is null"); return json; } RLog.D.p("getVeriest -> " + type == null ? " non-type" : type.getSimpleName()); if (ReflectUtils.isImplements(type, Map.class)) { RLog.D.p("build map"); return buildMap(json, type, ReflectUtils.buildMap(type)); } else if (ReflectUtils.isImplements(type, List.class)) { RLog.D.p("build list"); return buildList(json, type, ReflectUtils.buildList(type)); } else if (ReflectUtils.isImplements(type, Set.class)) { RLog.D.p("build set"); return buildSet(json, type, ReflectUtils.buildSet(type)); } else if (ReflectUtils.isImplements(type, JsonBean.class)) { RLog.D.p("build other bean"); return buildOtherBean(json, type); } else { RLog.D.p("build common"); return json; } } private Object buildOtherBean(Object json, Class<?> type) throws JSONException { String jsonStr = json.toString(); RLog.D.p("build other bean -> json: " + json + " type: " + type.getSimpleName()); return JProperty.reverseBuild(jsonStr, type); } private Set<Object> buildSet(Object json, Class<?> type, Set<Object> set) throws JSONException { // now , i'm sure the json should be 'JsonArray' JSONArray array = (JSONArray) json; // get the next generice Class<?> generice = mGenericQueue.poll(); for (int i = 0; i < array.length(); i++) { set.add(getVeriest(array.get(i), generice)); } return set; } private List<Object> buildList(Object json, Class<?> type, List<Object> list) throws JSONException { // now , i'm sure the 'json' should be 'JsonArray' // don't worry cast exception,let's do it... JSONArray array = (JSONArray) json; // get the next generice Class<?> generice = mGenericQueue.poll(); for (int i = 0; i < array.length(); i++) { list.add(getVeriest(array.get(i), generice)); } return list; } private Map<Object, Object> buildMap(Object json, Class<?> type, Map<Object, Object> map) throws JSONException { // now , i'm sure the 'json' should be 'JsonObject' // don't worry cast exception,let's do it... JSONObject jobj = (JSONObject) json; Class<?> g1 = mGenericQueue.poll(); Class<?> g2 = mGenericQueue.poll(); for (Iterator<Object> iterator2 = jobj.keys(); iterator2.hasNext();) { Object key = iterator2.next(); Object value = jobj.get(key.toString()); map.put(getVeriest(key, g1), getVeriest(value, g2)); } return map; } }