I have come up with 3 approaches to creating object literals given the current JsInterop capabilities:
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
int field1;
String field2;
}
SomeObjectLiteral o = new SomeObjectLiteral();
o.field1 = 1;
o.field2 = "Some value";
2) Define a fluent interface
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
int field1;
String field2;
@JsOverlay
public final SomeObjectLiteral Field1(int v) {
field1 = v;
return this;
}
@JsOverlay
public final SomeObjectLiteral Field2(String v) {
field2 = v;
return this;
}
}
You can then write
new SomeObjectLiteral().Field1(1).Field2("A value");
Note I didn't call the setter setFieldx. This is because you currently get a runtime error if you do this.
2) Use an ObjectLiteral Helper
You can define a helper similar to
public class ObjectLiteral {
public static <O> O $(O base, Object ...fieldValues) {
String fieldName = null;
for(Object f : fieldValues) {
if (fieldName == null)
fieldName = (String)f;
else {
if (f instanceof Integer)
setField(base, fieldName, ((Integer) f).intValue());
else if (f instanceof Double)
setField(base, fieldName, ((Double) f).doubleValue());
else if (f instanceof Boolean)
setField(base, fieldName, ((Boolean) f).booleanValue());
else
setField(base, fieldName, f);
fieldName = null;
}
}
return base;
}
private final static native void setField(Object literal, String fieldName, int i) /*-{
literal[fieldName] = i;
}-*/;
private final static native void setField(Object literal, String fieldName, double d) /*-{
literal[fieldName] = d;
}-*/;
private final static native void setField(Object literal, String fieldName, boolean b) /*-{
literal[fieldName] = b;
}-*/;
private final static native void setField(Object literal, String fieldName, Object o) /*-{
literal[fieldName] = o;
}-*/;
}
You can then write
import static com.xxx.ObjectLiteral.$;
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
int field1;
String field2;
}
$(new SomeObjectLiteral(), "field1",123, "field2","some value")
You would probably want to add some more error checking to the helper. This approach probably isn't
particularly efficient, especially if you pass a lot of field values that get boxed into Object primitives.
It would be nice if the compiler unboxed varargs passed to isNative=true methods. If this was true you
could write a much more efficient javascript version.