/* * */ package org.smartly.commons.io.serialization.json.serializer; import org.json.JSONArray; import org.json.JSONObject; import org.smartly.IConstants; import org.smartly.commons.io.serialization.json.utils.JsonBeanUtils; import org.smartly.commons.util.StringUtils; import java.lang.reflect.Method; import java.util.Collection; import java.util.Date; import java.util.Map; import java.util.Set; /** * @author angelo.geminiani */ public class BeanSerializer { /** * Serialzie object wrapping it in a JsonBean * * @param object * @return */ public JSONObject serialize(final Object object) { final JSONObject result = new JSONObject(); try { if (null != object) { if (object instanceof Throwable) { JsonBeanUtils.addError(result, (Throwable) object); } else { final Object serialized = this.serialize( new BeanSerializerState(), null, object); JsonBeanUtils.addObject(result, object.getClass().getName(), serialized); } } } catch (Throwable t) { JsonBeanUtils.addError(result, t); } return result; } /** * Serialize in a pure JSON raw object * * @param object * @return */ public JSONObject rawSerialize(final Object object) { final Object serialized = this.serialize( new BeanSerializerState(), null, object); if (serialized instanceof JSONObject) { return (JSONObject) serialized; } return null; } // ------------------------------------------------------------------------ // p r i v a t e // ------------------------------------------------------------------------ private Object serialize(final BeanSerializerState state, final Object parent, final Object object) { if (null != object) { try { if (JsonBeanUtils.isNative(object)) { // native (String, long, Long, int, Integer, ...) return object; } else if (JsonBeanUtils.isDate(object)) { // date return ((Date) object).getTime(); } else if (object instanceof Collection || object.getClass().isArray()) { // array or collection return this.serializeCollection( state, parent, object); } else if (object instanceof Map) { return this.serializeMap(state, parent, (Map) object); } else if (object instanceof JSONObject) { return this.serializeJSONObject(state, parent, (JSONObject) object); } else if (object instanceof JSONArray) { return this.serializeJSONArray(state, parent, (JSONArray) object); } else if (StringUtils.isJSONObject(object)) { return this.serializeObject(state, parent, object); //object.toString(); } else if (StringUtils.isJSONArray(object)) { return this.serializeArray(state, parent, object); //object.toString(); } else { // bean return this.serializeBean(state, parent, object); } } catch (Throwable t) { return JsonBeanUtils.addError(new JSONObject(), t); } } return IConstants.NULL; // empty object } private JSONArray serializeCollection(final BeanSerializerState state, final Object parent, final Object object) { if (object instanceof Collection) { final Collection collection = (Collection) object; return this.serializeCollection(state, parent, collection.toArray(new Object[collection.size()])); } else if (object.getClass().isArray()) { return this.serializeCollection(state, parent, (Object[]) object); } else { return this.serializeCollection(state, parent, new Object[0]); } } private JSONArray serializeCollection(final BeanSerializerState state, final Object parent, final Object[] objects) { final JSONArray result = new JSONArray(); if (objects.length > 0) { for (final Object object : objects) { this.putInArray(state, parent, object, result); } } else { return result.put(IConstants.NULL); // avoid empty array } return result; } private JSONObject serializeMap(final BeanSerializerState state, final Object parent, final Map map) { final JSONObject result = new JSONObject(); final Set keys = map.keySet(); for (final Object key : keys) { final Object object = map.get(key); this.putInObject(state, parent, key.toString(), object, result); } return result; } private JSONObject serializeObject(final BeanSerializerState state, final Object parent, final Object object) { JSONObject result = new JSONObject(); try { result = new JSONObject(object.toString()); } catch (Throwable t) { JsonBeanUtils.addError(result, t); } return result; } private Object serializeArray(final BeanSerializerState state, final Object parent, final Object object) { try { return new JSONArray(object.toString()); } catch (Throwable t) { return JsonBeanUtils.addError(new JSONObject(), t); } } private JSONObject serializeJSONObject(final BeanSerializerState state, final Object parent, final JSONObject jsonobject) { final JSONObject result = new JSONObject(); final JSONArray keys = jsonobject.names(); if (null != keys) { for (int i = 0; i < keys.length(); i++) { final String key = keys.optString(i); final Object object = jsonobject.opt(key); this.putInObject(state, parent, key, object, result); } } return result; } private JSONArray serializeJSONArray(final BeanSerializerState state, final Object parent, final JSONArray jsonarray) { final JSONArray result = new JSONArray(); for (int i = 0; i < jsonarray.length(); i++) { final Object object = jsonarray.opt(i); this.putInArray(state, parent, object, result); } return result; } private Object serializeBean(final BeanSerializerState state, final Object parent, final Object object) { final JSONObject result = new JSONObject(); if (!state.isProcessed(object)) { final BeanProcessed processed = state.addProcessedBean(parent, object); final Map<String, Method> methods = processed.getBeanData().getReadableProps(); final Set<String> names = methods.keySet(); for (final String name : names) { final Method method = methods.get(name); Object resultValue; try { resultValue = method.invoke(object, new Object[0]); result.put(name, this.serialize(state, parent, resultValue)); } catch (Throwable t) { JsonBeanUtils.addError(result, t); } } } else { return state.getProcessedBean(object).getBeanId(); } return result; } private void putInArray(final BeanSerializerState state, final Object parent, final Object object, final JSONArray result) { if (null != object) { if (JsonBeanUtils.isNative(object)) { result.put(object); //} else if (object instanceof DBObject) { // result.set(object.toString()); } else { if (!state.isProcessed(object)) { result.put(this.serialize(state, parent, object)); } else { result.put(state.getProcessedBean(object).getBeanId()); } } } } private void putInObject(final BeanSerializerState state, final Object parent, final String key, final Object object, final JSONObject result) { if (null != object) { try { if (JsonBeanUtils.isNative(object)) { result.put(key.toString(), object); //} else if (object instanceof DBObject) { // result.set(key.toString(), object.toString()); } else { if (!state.isProcessed(object)) { result.put(key, this.serialize(state, parent, object)); } else { result.put(key, state.getProcessedBean(object).getBeanId()); } } } catch (Throwable t) { } } } // ------------------------------------------------------------------------ // S T A T I C // ------------------------------------------------------------------------ private static BeanSerializer __instance; public static BeanSerializer getInstance() { if (null == __instance) { __instance = new BeanSerializer(); } return __instance; } }