Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ailabs-software/92ecfaee7a73ebf2c59e98708f7cb201 to your computer and use it in GitHub Desktop.
Save ailabs-software/92ecfaee7a73ebf2c59e98708f7cb201 to your computer and use it in GitHub Desktop.
package shopwindowshared.client.entrypoint;
import ailabs.jclosure.client.dom.NativeObject;
import ailabs.jclosure.client.encoding.json.JsonParser;
/** @fileoverview Prevents Java objects from being passed back to JS by proxying methods */
public class NativeToJavaObjectProxy extends NativeObject
{
protected NativeToJavaObjectProxy()
{
// Constructor as required.
}
private native void proxyJsMethods(Object javaObject) /*-{
function proxyFunctionFactory(key)
{
return function proxyFunction()
{
var returnValue = javaObject[key].apply(javaObject, arguments);
return @shopwindowshared.client.entrypoint.NativeToJavaObjectProxy::transformValue(Ljava/lang/Object;)(returnValue);
};
}
for (var key in javaObject)
{
if (typeof javaObject[key] == "function") {
this[key] = proxyFunctionFactory(key);
}
}
}-*/;
private static final Object transformValue(Object obj)
{
return JsonParser.toNativeObject(obj);
}
public static NativeToJavaObjectProxy create(Object javaObject)
{
NativeToJavaObjectProxy proxy = NativeObject.create().<NativeToJavaObjectProxy>as();
proxy.proxyJsMethods(javaObject);
return proxy;
}
}
package ailabs.jclosure.client.encoding.json;
import java.util.List;
import ailabs.jclosure.client.dom.NativeObject;
/** Implementation: JsonParser.
RULE: All arrays are ArrayLists that come from this.
Converts all JS arrays to ArrayLists (and ArrayLists back to JS arrays during serialization) */
public class JsonParser
{
public static NativeObject deserialize(String buf)
{
return deserialize(buf, true); // Default is to revive Java types (ArrayList namely)
}
public static native NativeObject deserialize(String buf, boolean reviveJavaTypes) /*-{
var reviverFunc = null;
if (reviveJavaTypes) {
reviverFunc = @ailabs.jclosure.client.encoding.json.JsonParser::reviverFunc(Ljava/lang/String;Lailabs/jclosure/client/dom/NativeObject;);
}
return $wnd.JSON.parse(buf, reviverFunc);
}-*/;
/** Converts all arrays to ArrayLists on deserialization. */
private static Object reviverFunc(String key, NativeObject obj)
{
if ( obj.isArray() ) {
return obj.copyToArrayList(); // ArrayList is wanted.
}
else {
return obj;
}
}
public static String serialize(Object obj)
{
if (obj != null) {
return serialize_(obj);
}
else {
return "null"; // Serialized representation of null
}
}
private static native String serialize_(Object obj) /*-{
return $wnd.JSON.stringify(obj, @ailabs.jclosure.client.encoding.json.JsonParser::replacerFunc(Ljava/lang/String;Ljava/lang/Object;) );
}-*/;
/** Converts all ArrayLists back to arrays on serialization. */
private static Object replacerFunc(String key, Object obj)
{
// TODO: Remove this kludge once https://github.com/gwtproject/gwt/issues/9482 issue is resolved and GWT is updated locally.
if ( NativeObject.isNonNullJsObject(obj) ) {
if (obj instanceof Number) {
return ( (Number) obj).doubleValue(); // Ints must be unwrapped back to JS numbers safely.
}
else if (obj instanceof List ) { // Typeof object in JS check prevents number from being instanceof'd
return ( ( List<Object> ) obj).toArray(); // JS array wanted, yes we know shhh
}
}
return obj;
}
/** Inefficient methods which are useful in a bind. Gets ArrayLists converted.
Return value is NativeObject, but any arrays will be proper Lists. */
public static NativeObject toJavaObject(Object obj)
{
return JsonParser.deserialize( JsonParser.serialize(obj) );
}
/** Converts back to JS objects. */
public static NativeObject toNativeObject(Object obj)
{
return JsonParser.deserialize( JsonParser.serialize(obj), false); // Do not revive.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment