package com.foundation.util.json; import java.io.IOException; import java.io.StringWriter; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.common.comparison.Comparator; import com.common.debug.Debug; import com.common.exception.InvalidArgumentException; import com.common.util.IIterator; import com.common.util.LiteHashMap; import com.common.util.LiteHashSet; import com.common.util.LiteList; import com.foundation.common.Entity; import com.foundation.common.MetadataContainer; /** * Reads and writes JSON formatted data. * Uses hashmaps and lists for the java side data structure. */ public class JsonBuilder { private JsonBuilder() { }//JsonBuilder()// private static LiteHashMap readObject(JSONObject object) throws JSONException { String[] keys = JSONObject.getNames(object); LiteHashMap result = new LiteHashMap(keys.length > 10 ? keys.length : 10); for(int index = 0; index < keys.length; index++) { Object value = object.get(keys[index]); if(value instanceof JSONObject) { value = readObject((JSONObject) value); }//if// else if(value instanceof JSONArray) { value = readArray((JSONArray) value); }//else if// else if(value == JSONObject.NULL) { value = null; }//else if// result.put(keys[index], value); }//for// return result; }//readObject()// private static LiteList readArray(JSONArray array) throws JSONException { LiteList result = new LiteList(array.length() > 10 ? array.length() : 10); for(int index = 0; index < array.length(); index++) { Object value = array.get(index); if(value instanceof JSONObject) { value = readObject((JSONObject) value); }//if// else if(value instanceof JSONArray) { value = readArray((JSONArray) value); }//else if// else if(value == JSONObject.NULL) { value = null; }//else if// result.add(value); }//for// return result; }//readArray()// /** * Converts the JSON string into a collection of LiteHashMap and LiteList instances. * @param json * @return */ public static LiteHashMap readJson(String json) { try { JSONTokener tokener = new JSONTokener(json); //TODO: It may be an array starting the JSON, not an object. JSONObject object = new JSONObject(tokener); return readObject(object); }//try// catch(JSONException e) { Debug.log(e); throw new InvalidArgumentException("Invalid JSON string."); }//catch// }//readJson()// private static JSONObject writeObject(LiteHashMap object) throws JSONException { JSONObject result = new JSONObject(); for(IIterator iterator = object.keyIterator(); iterator.hasNext(); ) { String key = (String) iterator.next(); Object value = object.get(key); if(value instanceof LiteHashMap) { value = writeObject((LiteHashMap) value); }//if// else if(value instanceof LiteList) { value = writeArray((LiteList) value); }//else if// else if(value == null) { value = JSONObject.NULL; }//else if// result.put(key, value); }//for// return result; }//writeObject()// private static JSONArray writeArray(LiteList array) throws JSONException { JSONArray result = new JSONArray(); for(int index = 0; index < array.getSize(); index++) { Object value = array.get(index); if(value instanceof LiteHashMap) { value = writeObject((LiteHashMap) value); }//if// else if(value instanceof LiteList) { value = writeArray((LiteList) value); }//else if// else if(value == null) { value = JSONObject.NULL; }//else if// result.put(value); }//for// return result; }//writeArray()// /** * Converts the value into a compact JSON string. * Includes all attributes that are not cyclical. * @param value The value to be converted (it will delve into collections and examine Entity objects to build the JSON string). * @return The JSON formatted string for the tree of objects. */ public static String writeJson(Object value) { return writeJson(value, null, null); }//writeJson()// /** * Converts the value into a JSON string. * Includes all attributes that are not cyclical. * @param indent The indent string to be used, or null if spacing should be minimized. * @return The JSON formatted string for the tree of objects. */ public static String writeJson(Object value, String indent) { return writeJson(value, null, indent); }//toJson()// /** * Converts the value into a compact JSON string. * Includes all attributes that are not cyclical. * @param metadataContainer The container containing metadata on what to include in the JSON. * @return The JSON formatted string for the tree of objects. */ public static String writeJson(Object value, MetadataContainer metadataContainer) { return writeJson(value, metadataContainer, null); }//toJson()// /** * Converts the value into a JSON string. * Includes all attributes that are not cyclical. * @param metadataContainer The container containing metadata on what to include in the JSON. * @param indent The indent string to be used, or null if spacing should be minimized. * @return The JSON formatted string for the tree of objects. */ public static String writeJson(Object value, MetadataContainer metadataContainer, String indent) { StringWriter writer = new StringWriter(10000); if(value != null) { try { Entity.jsonValue(value, metadataContainer, indent, 0, new LiteHashSet(100, Comparator.getIdentityComparator(), LiteHashSet.STYLE_NO_DUPLICATES), writer); }//try// catch(IOException e) { //Shouldn't ever occur.// Debug.log(e); }//catch// catch(Throwable e) { Debug.log(e); }//catch// }//if// return writer.toString(); }//toJson()// }//JsonBuilder//