All Downloads are FREE. Search and download functionalities are using the official Maven repository.

DataTools.ConvertObjectToJson Maven / Gradle / Ivy

package DataTools;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 Copyright 2016 Alianza Inc.

 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.

 */

/**
    Generates various types of randomized unique data
 */
public class ConvertObjectToJson {

    /**
     * Converts a data model into a JSONObject
     * @param model Data model to be converted
     * @return JSONObject
     */
    public  JSONObject convertToJson(T model) {
        JSONObject json = null;
        try {
            json = removeNull(handleEnums(model));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }

    /**
     * If the key or value of a JSONObject is null, remove that key (recursive function for JSONObjects within JSONObjects)
     * @param json JSONObject to remove null from
     * @return JSONObject
     */
    private JSONObject removeNull(JSONObject json) {
        Iterator keys = null;

        try {
            keys = new JSONObject(json.toString()).keys();
        } catch (JSONException e) {
            e.printStackTrace();
        }

        //full json has null for non populated data, we just remove those
        for (String key : iterable(keys)) {
            try {
                if (json.isNull(key) || json.getString(key).startsWith("null") || json.getString(key).equals("{}"))
                    json.remove(key);
                //handle recursive json objects
                else if (json.getString(key).startsWith("{") && json.getString(key).endsWith("}"))
                    json.put(key, removeNull(new JSONObject(json.getString(key))));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return json;
    }

    /**
     * Used for looping through json keys
     * @param it
     * @param 
     * @return it
     */
    private static  Iterable iterable(final Iterator it) {
        return () -> it;
    }

    /**
     * this method takes a model with all its data set
     * returns a json object of the model,
     * all fields from the model will be in the json object
     * null values will need to be removed *removeNull(handleEnums(model)
     * method is complex because of handling the enums,
     * normal conversion to json with enums present will cause failures
     * @param model Data model to convert to Json
     * @return JSONObject
     */
    private JSONObject handleEnums(Object model) {
        JSONObject json = new JSONObject();
        Method[] methods = model.getClass().getMethods();
        String modelType = ".model";
        String enumType = ".type";

        //populate new one, leave out enum fields
        for (Method get : methods) {
            //setup by finding gets and sets
            String methName = get.getName();

            try {
                //check to see if it is a method call we care about it
                if ((methName.startsWith("get") || methName.startsWith("is")) && get.getParameterCount() == 0 && get.invoke(model) != null) {
                    Package returnType = get.getReturnType().getPackage();

                    //handle if it is a list
                    if (get.invoke(model) instanceof java.util.List) {
                        List list = (List) get.invoke(model);
                        JSONArray jarray = new JSONArray();
                        for (Object obj : list) {
                            if (obj.getClass().getPackage().toString().endsWith(modelType)) {
                                jarray.put(handleEnums(obj));
                            } else {
                                jarray.put(obj);
                            }
                        }
                        json.put(formatName(methName), jarray);
                    }
                    else if (get.invoke(model) instanceof java.util.Map) {
                        Map map = (Map) get.invoke(model);
                        JSONObject mapObject = new JSONObject();
                        for (Map.Entry entry : map.entrySet()) {
                            String key = entry.getKey().getClass().isEnum() ? ((Enum)entry.getKey()).name() : entry.getKey().toString();
                            mapObject.put(key, handleEnums(entry.getValue()));
                        }
                        json.put(formatName(methName), mapObject);
                    }
                    else {
                        //get from original object and set in json,
                        //copying individual field over
                        if (get.invoke(model).getClass().isEnum()) {
                            Object value = get.invoke(model);
                            if (value.toString().contains("_") && methName.contains("TimeZone")) {
                                json.put(formatName(methName), value.toString().replace("_", "/"));
                            } else {
                                json.put(formatName(methName), ((Enum)get.invoke(model)).name());
                            }
                        } else if (returnType != null &&
                                returnType.toString().endsWith(modelType) &&
                                !returnType.toString().endsWith(enumType)) {
                            json.put(formatName(methName), handleEnums(get.invoke(model)));
                        } else {
                            //timezones have a _ in enum but need a / in the string
                            json.put(formatName(methName), get.invoke(model));
                        }
                    }
                }
                //just try the next method if you get an error
            } catch (InvocationTargetException|JSONException|IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        //gets added because reflection and we will never want it
        json.remove("class");
        return json;
    }

    /**
     * Formats a method name
     * @param name Method name
     * @return String
     */
    private String formatName(String name) {
        String nameChange = name.substring(0, 3).replace("get", "").replace("is", "") + name.substring(3);
        nameChange = Character.toLowerCase(nameChange.charAt(0)) + nameChange.substring(1);
        return nameChange;
    }
}