package local.json.javascript;
import java.util.Iterator;
import net.sf.json.*;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.IdScriptableObject;
import org.mozilla.javascript.NativeArray;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.NativeObject;
/**
* Collection of JSON Utility methods.
*
*/
public class Js2JSONUtils
{
/**
* Converts a given JavaScript native object and converts it to the relevant JSON string.
*
* @param object JavaScript object
* @return String JSON
*/
public String toJSONString(Object object)
{
if (object instanceof NativeArray)
{
return nativeArrayToJSONString((NativeArray)object);
}
else if (object instanceof NativeObject)
{
return nativeObjectToJSONString((NativeObject)object);
}
return null;
}
/**
* Takes a JSON string and converts it to a native java script object
*
* @param jsonString a valid json string
* @return NativeObject the created native JS object that represents the JSON object
*/
public NativeObject toObject(String jsonString)
{
// TODO deal with json array stirngs
// Parse JSON string
try {
JSONObject jsonObject = (JSONObject) JSONSerializer.toJSON(jsonString);
// Create native object
return toObject(jsonObject);
} catch(Exception e){
e.printStackTrace();
}
return null;
}
/**
* Takes a JSON object and converts it to a native JS object.
*
* @param jsonObject the json object
* @return NativeObject the created native object
*/
public NativeObject toObject(JSONObject jsonObject)
{
// Create native object
NativeObject object = new NativeObject();
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext())
{
String key = (String)keys.next();
Object value = jsonObject.get(key);
if (value instanceof JSONObject)
{
object.put(key, object, toObject((JSONObject)value));
}
else
{
object.put(key, object, value);
}
}
return object;
}
/**
* Build a JSON string for a native object
*
* @param nativeObject
* @param json
*/
private String nativeObjectToJSONString(NativeObject nativeObject)
{
JSONObject json = new JSONObject();
Object[] ids = nativeObject.getIds();
for (Object id : ids)
{
String key = id.toString();
Object value = nativeObject.get(key, nativeObject);
json.put(key, valueToJSONString(value));
}
return json.toString();
}
/**
* Build JSON string for a native array
*
* @param nativeArray
*/
private String nativeArrayToJSONString(NativeArray nativeArray)
{
Object[] propIds = nativeArray.getIds();
if (isArray(propIds) == true)
{
JSONArray jsonArray = new JSONArray();
for (int i=0; i<propIds.length; i++)
{
Object propId = propIds[i];
if (propId instanceof Integer)
{
Object value = nativeArray.get((Integer)propId, nativeArray);
jsonArray.add(valueToJSONString(value));
}
}
return jsonArray.toString();
}
else
{
JSONObject json = new JSONObject();
for (Object propId : propIds)
{
Object value = nativeArray.get(propId.toString(), nativeArray);
json.put(propId.toString(), valueToJSONString(value));
}
return json.toString();
}
}
/**
* Look at the id's of a native array and try to determine whether it's actually an Array or a HashMap
*
* @param ids id's of the native array
* @return boolean true if it's an array, false otherwise (ie it's a map)
*/
private boolean isArray(Object[] ids)
{
boolean result = true;
for (Object id : ids)
{
if (id instanceof Integer == false)
{
result = false;
break;
}
}
return result;
}
/**
* Convert value to JSON string
*
* @param value
*/
private String valueToJSONString(Object value)
{
JSONObject json = new JSONObject();
if (value instanceof IdScriptableObject &&
((IdScriptableObject)value).getClassName().equals("Date") == true)
{
// Get the UTC values of the date
Object year = NativeObject.callMethod((IdScriptableObject)value, "getUTCFullYear", null);
Object month = NativeObject.callMethod((IdScriptableObject)value, "getUTCMonth", null);
Object date = NativeObject.callMethod((IdScriptableObject)value, "getUTCDate", null);
Object hours = NativeObject.callMethod((IdScriptableObject)value, "getUTCHours", null);
Object minutes = NativeObject.callMethod((IdScriptableObject)value, "getUTCMinutes", null);
Object seconds = NativeObject.callMethod((IdScriptableObject)value, "getUTCSeconds", null);
Object milliSeconds = NativeObject.callMethod((IdScriptableObject)value, "getUTCMilliseconds", null);
// Build the JSON object to represent the UTC date
json.put("zone","UTC");
json.put("year",year);
json.put("month",month);
json.put("date",date);
json.put("hours",hours);
json.put("minutes",minutes);
json.put("seconds",seconds);
json.put("milliseconds",milliSeconds);
return json.toString();
}
else if (value instanceof NativeJavaObject)
{
Object javaValue = Context.jsToJava(value, Object.class);
return javaValue.toString();
}
else if (value instanceof NativeArray)
{
// Output the native array
return nativeArrayToJSONString((NativeArray)value);
}
else if (value instanceof NativeObject)
{
// Output the native object
return nativeObjectToJSONString((NativeObject)value);
}
else
{
return value.toString();
}
}
}