com.browseengine.bobo.serialize.JSONSerializer.java Source code

Java tutorial

Introduction

Here is the source code for com.browseengine.bobo.serialize.JSONSerializer.java

Source

/**
 * Bobo Browse Engine - High performance faceted/parametric search implementation 
 * that handles various types of semi-structured data.  Written in Java.
 * 
 * Copyright (C) 2005-2006  John Wang
 *
 * This library 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 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * To contact the project administrators for the bobo-browse project, 
 * please go to https://sourceforge.net/projects/bobo-browse/, or 
 * send mail to owner@browseengine.com.
 */

package com.browseengine.bobo.serialize;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.browseengine.bobo.serialize.JSONSerializable.JSONSerializationException;

public class JSONSerializer {
    private static Logger logger = Logger.getLogger(JSONSerializer.class);

    private static void loadObject(Object array, Class type, int index, JSONArray jsonArray)
            throws JSONSerializationException, JSONException {
        if (type.isPrimitive()) {
            if (type == Integer.TYPE) {
                Array.setInt(array, index, jsonArray.getInt(index));
            } else if (type == Long.TYPE) {
                Array.setLong(array, index, jsonArray.getInt(index));
            } else if (type == Short.TYPE) {
                Array.setShort(array, index, (short) jsonArray.getInt(index));
            } else if (type == Boolean.TYPE) {
                Array.setBoolean(array, index, jsonArray.getBoolean(index));
            } else if (type == Double.TYPE) {
                Array.setDouble(array, index, jsonArray.getDouble(index));
            } else if (type == Float.TYPE) {
                Array.setFloat(array, index, (float) jsonArray.getDouble(index));
            } else if (type == Character.TYPE) {
                char ch = jsonArray.getString(index).charAt(0);
                Array.setChar(array, index, ch);
            } else if (type == Byte.TYPE) {
                Array.setByte(array, index, (byte) jsonArray.getInt(index));
            } else {
                throw new JSONSerializationException("Unknown primitive: " + type);
            }
        } else if (type == String.class) {
            Array.set(array, index, jsonArray.getString(index));
        } else if (JSONSerializable.class.isAssignableFrom(type)) {
            JSONObject jObj = jsonArray.getJSONObject(index);
            JSONSerializable serObj = deSerialize(type, jObj);
            Array.set(array, index, serObj);
        } else if (type.isArray()) {
            Class componentClass = type.getComponentType();
            JSONArray subArray = jsonArray.getJSONArray(index);
            int len = subArray.length();

            Object newArray = Array.newInstance(componentClass, len);
            for (int k = 0; k < len; ++k) {
                loadObject(newArray, componentClass, k, subArray);
            }
        }
    }

    private static void loadObject(Object retObj, Field f, JSONObject jsonObj) throws JSONSerializationException {
        String key = f.getName();
        Class type = f.getType();
        try {
            if (type.isPrimitive()) {
                if (type == Integer.TYPE) {
                    f.setInt(retObj, jsonObj.getInt(key));
                } else if (type == Long.TYPE) {
                    f.setLong(retObj, jsonObj.getInt(key));
                } else if (type == Short.TYPE) {
                    f.setShort(retObj, (short) jsonObj.getInt(key));
                } else if (type == Boolean.TYPE) {
                    f.setBoolean(retObj, jsonObj.getBoolean(key));
                } else if (type == Double.TYPE) {
                    f.setDouble(retObj, jsonObj.getDouble(key));
                } else if (type == Float.TYPE) {
                    f.setFloat(retObj, (float) jsonObj.getDouble(key));
                } else if (type == Character.TYPE) {
                    char ch = jsonObj.getString(key).charAt(0);
                    f.setChar(retObj, ch);
                } else if (type == Byte.TYPE) {
                    f.setByte(retObj, (byte) jsonObj.getInt(key));
                } else {
                    throw new JSONSerializationException("Unknown primitive: " + type);
                }
            } else if (type == String.class) {
                f.set(retObj, jsonObj.getString(key));
            } else if (JSONSerializable.class.isAssignableFrom(type)) {
                JSONObject jObj = jsonObj.getJSONObject(key);
                JSONSerializable serObj = deSerialize(type, jObj);
                f.set(retObj, serObj);
            }
        } catch (Exception e) {
            throw new JSONSerializationException(e.getMessage(), e);
        }
    }

    public static JSONSerializable deSerialize(Class clz, JSONObject jsonObj)
            throws JSONSerializationException, JSONException {
        Iterator iter = jsonObj.keys();

        if (!JSONSerializable.class.isAssignableFrom(clz)) {
            throw new JSONSerializationException(clz + " is not an instance of " + JSONSerializable.class);
        }

        JSONSerializable retObj;
        try {
            retObj = (JSONSerializable) clz.newInstance();
        } catch (Exception e1) {
            throw new JSONSerializationException(
                    "trouble with no-arg instantiation of " + clz.toString() + ": " + e1.getMessage(), e1);
        }

        if (JSONExternalizable.class.isAssignableFrom(clz)) {
            ((JSONExternalizable) retObj).fromJSON(jsonObj);
            return retObj;
        }

        while (iter.hasNext()) {
            String key = (String) iter.next();

            try {
                Field f = clz.getDeclaredField(key);
                if (f != null) {
                    f.setAccessible(true);
                    Class type = f.getType();

                    if (type.isArray()) {
                        JSONArray array = jsonObj.getJSONArray(key);
                        int len = array.length();
                        Class cls = type.getComponentType();

                        Object newArray = Array.newInstance(cls, len);
                        for (int k = 0; k < len; ++k) {
                            loadObject(newArray, cls, k, array);
                        }
                        f.set(retObj, newArray);
                    } else {
                        loadObject(retObj, f, jsonObj);
                    }
                }
            } catch (Exception e) {
                throw new JSONSerializationException(e.getMessage(), e);
            }
        }

        return retObj;
    }

    private static void dumpObject(JSONObject jsonObj, Field f, JSONSerializable srcObj)
            throws JSONSerializationException, JSONException {
        Object value;
        try {
            value = f.get(srcObj);
        } catch (Exception e) {
            throw new JSONSerializationException(e.getMessage(), e);
        }

        Class type = f.getType();

        String name = f.getName();

        if (type.isPrimitive()) {
            jsonObj.put(name, String.valueOf(value));
        } else if (type == String.class) {
            if (value != null) {
                jsonObj.put(name, String.valueOf(value));
            }
        } else if (JSONSerializable.class.isInstance(value)) {
            jsonObj.put(name, serializeJSONObject((JSONSerializable) value));
        }
    }

    private static void dumpObject(JSONArray jsonArray, Class type, Object array, int index)
            throws JSONSerializationException, JSONException {
        if (type.isPrimitive()) {
            jsonArray.put(String.valueOf(Array.get(array, index)));
        } else if (type == String.class) {
            String val = (String) Array.get(array, index);
            if (val != null) {
                jsonArray.put(val);
            }
        } else if (JSONSerializable.class.isAssignableFrom(type)) {
            JSONSerializable o = (JSONSerializable) Array.get(array, index);
            JSONObject jobj = serializeJSONObject(o);
            jsonArray.put(jobj);
        } else if (type.isArray() && array != null) {
            Class compType = type.getComponentType();
            Object subArray = Array.get(array, index);
            int len = Array.getLength(subArray);
            JSONArray arr = new JSONArray();
            for (int k = 0; k < len; ++k) {
                dumpObject(arr, compType, subArray, k);
            }
            jsonArray.put(arr);
        }
    }

    public static JSONObject serializeJSONObject(JSONSerializable obj)
            throws JSONSerializationException, JSONException {
        if (obj instanceof JSONExternalizable) {
            return ((JSONExternalizable) obj).toJSON();
        }

        JSONObject jsonObj = new JSONObject();
        Class clz = obj.getClass();
        Field[] fields = clz.getDeclaredFields();

        for (int i = 0; i < fields.length; ++i) {
            fields[i].setAccessible(true);
            int modifiers = fields[i].getModifiers();
            if (!Modifier.isTransient(modifiers) && !Modifier.isStatic(modifiers)) {
                String name = fields[i].getName();
                Class type = fields[i].getType();

                try {
                    Object value = fields[i].get(obj);

                    if (type.isArray() && value != null) {
                        int len = Array.getLength(value);

                        Class cls = type.getComponentType();

                        JSONArray array = new JSONArray();

                        for (int k = 0; k < len; ++k) {
                            dumpObject(array, cls, value, k);
                        }
                        jsonObj.put(name, array);
                    } else {
                        dumpObject(jsonObj, fields[i], obj);
                    }
                } catch (Exception e) {
                    throw new JSONSerializationException(e.getMessage(), e);
                }
            }
        }

        return jsonObj;
    }

    public static void main(String[] args) throws Exception {
        class B implements JSONSerializable {
            transient int tIntVal = 6;
            String s = "bstring";
            float[] fArray = new float[] { 1.3f, 1.2f, 2.5f };
        }
        class C implements JSONExternalizable {
            private HashMap<String, String> map = new HashMap<String, String>();

            public void fromJSON(JSONObject obj) throws JSONSerializationException, JSONException {
                map.clear();
                Iterator iter = obj.keys();
                while (iter.hasNext()) {
                    String key = (String) iter.next();
                    String val = obj.getString(key);
                    map.put(key, val);
                }
            }

            public JSONObject toJSON() throws JSONSerializationException, JSONException {
                JSONObject retVal = new JSONObject();
                Iterator<String> iter = map.keySet().iterator();
                while (iter.hasNext()) {
                    String name = iter.next();
                    String val = map.get(name);
                    retVal.put(name, val);
                }
                return retVal;
            }

            public void set(String name, String val) {
                map.put(name, val);
            }
        }
        class A implements JSONSerializable {
            int intVal = 4;
            double doubleVal = 1.2;
            short shortVal = 12;
            HashMap hash = new HashMap();
            int[] intArray = new int[] { 1, 3 };
            String[] strArray = new String[] { "john", "wang" };
            B[] b = new B[] { new B(), new B() };
            B b2 = new B();
            C c = new C();

            A() {
                c.set("city", "san jose");
                c.set("country", "usa");
            }
        }

        JSONObject jsonObj = JSONSerializer.serializeJSONObject(new A());

        String s1 = jsonObj.toString();

        System.out.println(s1);

        A a = (A) deSerialize(A.class, jsonObj);
        jsonObj = JSONSerializer.serializeJSONObject(a);
        String s2 = jsonObj.toString();

        System.out.println(s1.equals(s2));
    }
}