Java tutorial
/* ############################################################################### # # # Copyright (C) 2011-2015 OpenMEAP, Inc. # # Credits to Jonathan Schang & Rob Thacher # # # # Released under the LGPLv3 # # # # OpenMEAP is free software: you can redistribute it and/or modify # # it under the terms of the GNU Lesser General Public License as published # # by the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # OpenMEAP is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU Lesser General Public License for more details. # # # # You should have received a copy of the GNU Lesser General Public License # # along with OpenMEAP. If not, see <http://www.gnu.org/licenses/>. # # # ############################################################################### */ package com.openmeap.json; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import com.openmeap.json.HasJSONProperties; import com.openmeap.json.Enum; import com.openmeap.thirdparty.org.json.me.JSONArray; import com.openmeap.thirdparty.org.json.me.JSONException; import com.openmeap.thirdparty.org.json.me.JSONObject; /** * Converts an object hierarchy into a JSON representation. * Only looks at the JSONProperty annotated getter-methods. * Limited Hashtable support, but statically-typed arrays are good. * Assumes camel-case is desired. * Assumes the objects are instantiable without constructor arguments. * * @author schang */ public class JSONObjectBuilder { public Object fromJSON(JSONObject jsonObj, Object rootObject) throws JSONException { if (jsonObj == null) { return null; } if (!HasJSONProperties.class.isAssignableFrom(rootObject.getClass())) { throw new RuntimeException( "The rootObject being converted to JSON must implement the HashJSONProperties interface."); } JSONProperty[] properties = ((HasJSONProperties) rootObject).getJSONProperties(); for (int jsonPropertyIdx = 0; jsonPropertyIdx < properties.length; jsonPropertyIdx++) { JSONProperty property = properties[jsonPropertyIdx]; Class returnType = property.getReturnType(); String propertyName = property.getPropertyName(); try { // get the unparsed value from the JSONObject Object value = null; try { value = jsonObj.get(propertyName); } catch (JSONException e) { continue; } if (value == JSONObject.NULL) { continue; } if (Enum.class.isAssignableFrom(returnType)) { property.getGetterSetter().setValue(rootObject, value); } else if (value instanceof JSONArray) { JSONArray array = (JSONArray) value; Vector list = new Vector(); for (int i = 0; i < array.length(); i++) { Object obj = array.get(i); if (obj instanceof JSONObject) { Object newObj = (Object) returnType.newInstance(); list.addElement(fromJSON((JSONObject) obj, newObj)); } else { list.addElement(obj); } } if (property.getContainedType() != null) { property.getGetterSetter().setValue(rootObject, list); } else { property.getGetterSetter().setValue(rootObject, toTypedArray(list)); } } else if (value instanceof JSONObject) { Object obj = (Object) returnType.newInstance(); if (Hashtable.class.isAssignableFrom(returnType)) { Hashtable table = (Hashtable) obj; JSONObject jsonMap = (JSONObject) value; Enumeration keysEnum = jsonMap.keys(); while (keysEnum.hasMoreElements()) { String key = (String) keysEnum.nextElement(); Object thisValue = jsonMap.get(key); if (thisValue instanceof JSONObject) { Object newObj = (Object) returnType.newInstance(); table.put(key, fromJSON((JSONObject) thisValue, newObj)); } else { table.put(key, thisValue); } } property.getGetterSetter().setValue(rootObject, table); } else { // of the type correct for the property.getGetterSetter().setValue(rootObject, fromJSON((JSONObject) value, obj)); } } else if (isSimpleType(returnType)) { property.getGetterSetter().setValue(rootObject, correctCasting(returnType, value)); } } catch (Exception e) { throw new JSONException(e); } } return rootObject; } public JSONObject toJSON(Object obj) throws JSONException { if (obj == null) { return null; } if (!HasJSONProperties.class.isAssignableFrom(obj.getClass())) { throw new RuntimeException( "The rootObject being converted to JSON must implement the HasJSONProperties interface."); } JSONProperty[] properties = ((HasJSONProperties) obj).getJSONProperties(); JSONObject jsonObj = new JSONObject(); // iterate over each JSONProperty annotated method for (int jsonPropertyIdx = 0; jsonPropertyIdx < properties.length; jsonPropertyIdx++) { JSONProperty property = properties[jsonPropertyIdx]; // determine the method return type Class returnType = property.getReturnType(); Object value = property.getGetterSetter().getValue(obj); if (value == null) { continue; } if (returnType == null) { throw new JSONException(obj.getClass().getName() + "." + property.getPropertyName() + " is annotated with JSONProperty, but has no return type." + " I can't work with this."); } // strip "get" off the front String propertyName = property.getPropertyName(); try { if (Enum.class.isAssignableFrom(returnType)) { Enum ret = (Enum) value; jsonObj.put(propertyName, ret.value()); } else if (isSimpleType(returnType)) { jsonObj.put(propertyName, handleSimpleType(returnType, property.getGetterSetter().getValue(obj))); } else { if (returnType.isArray()) { Object[] returnValues = (Object[]) value; JSONArray jsonArray = new JSONArray(); for (int returnValueIdx = 0; returnValueIdx < returnValues.length; returnValueIdx++) { Object thisValue = returnValues[returnValueIdx]; jsonArray.put(toJSON(thisValue)); } jsonObj.put(propertyName, jsonArray); } else if (Hashtable.class.isAssignableFrom(returnType)) { Hashtable map = (Hashtable) value; JSONObject jsonMap = new JSONObject(); Enumeration enumer = map.keys(); while (enumer.hasMoreElements()) { Object key = (String) enumer.nextElement(); Object thisValue = (Object) map.get(key); if (isSimpleType(thisValue.getClass())) { jsonMap.put(key.toString(), handleSimpleType(returnType, thisValue)); } else { jsonMap.put(key.toString(), toJSON(thisValue)); } } jsonObj.put(propertyName, jsonMap); } else if (Vector.class.isAssignableFrom(returnType)) { Vector returnValues = (Vector) property.getGetterSetter().getValue(obj); JSONArray jsonArray = new JSONArray(); int size = returnValues.size(); for (int returnValueIdx = 0; returnValueIdx < size; returnValueIdx++) { Object thisValue = returnValues.elementAt(returnValueIdx); if (isSimpleType(property.getContainedType())) { jsonArray.put(thisValue); } else { jsonArray.put(toJSON(thisValue)); } } jsonObj.put(propertyName, jsonArray); } else { jsonObj.put(propertyName, toJSON(value)); } } } catch (Exception ite) { throw new JSONException(ite); } } return jsonObj; } private Object handleSimpleType(Class returnType, Object value) { if (returnType.isArray()) { Object[] returnValues = (Object[]) value; JSONArray jsonArray = new JSONArray(); for (int returnValuesIdx = 0; returnValuesIdx < returnValues.length; returnValuesIdx++) { Object thisValue = returnValues[returnValuesIdx]; jsonArray.put(thisValue); } return jsonArray; } else { return value; } } private Object[] toTypedArray(Vector list) { if (list.isEmpty()) { return null; } Object first = list.elementAt(0); Object[] ret = null; if (first instanceof String) { ret = new String[list.size()]; } else if (first instanceof Double) { ret = new Double[list.size()]; } else if (first instanceof Integer) { ret = new Integer[list.size()]; } else if (first instanceof Long) { ret = new Long[list.size()]; } else if (first instanceof Boolean) { ret = new Boolean[list.size()]; } list.copyInto(ret); return (Object[]) ret; } private Object correctCasting(Class type, Object obj) { if (type.equals(Long.class)) { return new Long(Long.parseLong(obj.toString())); } else if (type.equals(Double.class)) { return Double.valueOf(obj.toString()); } else if (type.equals(Integer.class)) { return Integer.valueOf(obj.toString()); } else return obj; } private boolean isSimpleType(Class returnType) { if (returnType.isArray()) { return Boolean[].class.isAssignableFrom(returnType) || Long[].class.isAssignableFrom(returnType) || Double[].class.isAssignableFrom(returnType) || Integer[].class.isAssignableFrom(returnType) || String[].class.isAssignableFrom(returnType); } else { return Boolean.class.isAssignableFrom(returnType) || Long.class.isAssignableFrom(returnType) || Double.class.isAssignableFrom(returnType) || Integer.class.isAssignableFrom(returnType) || String.class.isAssignableFrom(returnType); } } }