Change-Id: I2779a533811bb1b60c4e74789f6378574bc6ac61tags/7.4.0.beta2
@@ -47,6 +47,7 @@ import com.google.gwt.user.rebind.SourceWriter; | |||
import com.vaadin.client.JsArrayObject; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.client.annotations.OnStateChange; | |||
import com.vaadin.client.communication.JsonDecoder; | |||
import com.vaadin.client.metadata.ConnectorBundleLoader; | |||
import com.vaadin.client.metadata.ConnectorBundleLoader.CValUiInfo; | |||
import com.vaadin.client.metadata.InvokationHandler; | |||
@@ -1011,7 +1012,16 @@ public class ConnectorBundleLoaderFactory extends Generator { | |||
w.print(", "); | |||
} | |||
String parameterTypeName = getBoxedTypeName(parameterType); | |||
w.print("(" + parameterTypeName + ") params[" + i + "]"); | |||
if (parameterTypeName.startsWith("elemental.json.Json")) { | |||
// Need to pass through native method to allow casting Object to | |||
// JSO if the value is a string | |||
w.print("%s.<%s>obj2jso(params[%d])", | |||
JsonDecoder.class.getCanonicalName(), | |||
parameterTypeName, i); | |||
} else { | |||
w.print("(" + parameterTypeName + ") params[" + i + "]"); | |||
} | |||
} | |||
w.println(");"); | |||
@@ -82,13 +82,16 @@ public class JsonDecoder { | |||
*/ | |||
public static Object decodeValue(Type type, JsonValue jsonValue, | |||
Object target, ApplicationConnection connection) { | |||
String baseTypeName = type.getBaseTypeName(); | |||
if (baseTypeName.startsWith("elemental.json.Json")) { | |||
return jsonValue; | |||
} | |||
// Null is null, regardless of type | |||
// Null is null, regardless of type (except JSON) | |||
if (jsonValue.getType() == JsonType.NULL) { | |||
return null; | |||
} | |||
String baseTypeName = type.getBaseTypeName(); | |||
if (Map.class.getName().equals(baseTypeName) | |||
|| HashMap.class.getName().equals(baseTypeName)) { | |||
return decodeMap(type, jsonValue, connection); | |||
@@ -293,4 +296,14 @@ public class JsonDecoder { | |||
tokens.add(decodeValue(childType, entryValue, null, connection)); | |||
} | |||
} | |||
/** | |||
* Called by generated deserialization code to treat a generic object as a | |||
* JsonValue. This is needed because GWT refuses to directly cast String | |||
* typed as Object into a JSO. | |||
*/ | |||
public static native <T extends JsonValue> T obj2jso(Object object) | |||
/*-{ | |||
return object; | |||
}-*/; | |||
} |
@@ -300,7 +300,9 @@ public class JsonCodec implements Serializable { | |||
} | |||
// Try to decode object using fields | |||
if (value.getType() == JsonType.NULL) { | |||
if (isJsonType(targetType)) { | |||
return value; | |||
} else if (value.getType() == JsonType.NULL) { | |||
return null; | |||
} else if (targetType == byte.class || targetType == Byte.class) { | |||
return Byte.valueOf((byte) value.asNumber()); | |||
@@ -334,6 +336,11 @@ public class JsonCodec implements Serializable { | |||
} | |||
} | |||
private static boolean isJsonType(Type type) { | |||
return type instanceof Class<?> | |||
&& JsonValue.class.isAssignableFrom((Class<?>) type); | |||
} | |||
private static Object decodeArray(Type componentType, JsonArray value, | |||
ConnectorTracker connectorTracker) { | |||
Class<?> componentClass = getClassForType(componentType); |
@@ -42,10 +42,14 @@ import com.vaadin.tests.widgetset.client.SerializerTestState; | |||
import com.vaadin.tests.widgetset.client.SimpleTestBean; | |||
import com.vaadin.tests.widgetset.server.SerializerTestExtension; | |||
import elemental.json.Json; | |||
import elemental.json.JsonString; | |||
import elemental.json.JsonValue; | |||
@Widgetset("com.vaadin.tests.widgetset.TestingWidgetSet") | |||
public class SerializerTest extends AbstractTestUI { | |||
private Log log = new Log(40); | |||
private Log log = new Log(45); | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
@@ -256,6 +260,12 @@ public class SerializerTest extends AbstractTestUI { | |||
rpc.sendDate(new Date(1)); | |||
rpc.sendDate(new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13)); | |||
state.jsonNull = Json.createNull(); | |||
state.jsonString = Json.create("a string"); | |||
state.jsonBoolean = Json.create(false); | |||
rpc.sendJson(Json.create(true), Json.createNull(), Json.create("JSON")); | |||
state.date1 = new Date(1); | |||
state.date2 = new Date(2013 - 1900, 5 - 1, 31, 11, 12, 13); | |||
@@ -447,6 +457,13 @@ public class SerializerTest extends AbstractTestUI { | |||
log.log("sendDate: " + format.format(date)); | |||
} | |||
@Override | |||
public void sendJson(JsonValue value1, JsonValue value2, | |||
JsonString string) { | |||
log.log("sendJson: " + value1.toJson() + ", " + value2.toJson() | |||
+ ", " + string.toJson()); | |||
} | |||
@Override | |||
public void log(String string) { | |||
log.log(string); | |||
@@ -458,7 +475,7 @@ public class SerializerTest extends AbstractTestUI { | |||
@Override | |||
protected String getTestDescription() { | |||
return "Test for lots of different cases of encoding and decoding variuos data types"; | |||
return "Test for lots of different cases of encoding and decoding various data types"; | |||
} | |||
@Override |
@@ -27,6 +27,9 @@ public class SerializerTestTest extends MultiBrowserTest { | |||
openTestURL(); | |||
int logRow = 0; | |||
Assert.assertEquals( | |||
"sendJson: {\"b\":false,\"s\":\"JSON\"}, null, \"value\"", | |||
getLogRow(logRow++)); | |||
Assert.assertEquals("sendDate: May 31, 2013 8:12:13 AM UTC", | |||
getLogRow(logRow++)); | |||
Assert.assertEquals("sendDate: January 1, 1970 12:00:00 AM UTC", | |||
@@ -77,6 +80,9 @@ public class SerializerTestTest extends MultiBrowserTest { | |||
"sendBoolean: false, false, [false, false, true, false, true, true]", | |||
getLogRow(logRow++)); | |||
Assert.assertEquals("sendBeanSubclass: 43", getLogRow(logRow++)); | |||
Assert.assertEquals("state.jsonBoolean: false", getLogRow(logRow++)); | |||
Assert.assertEquals("state.jsonString: a string", getLogRow(logRow++)); | |||
Assert.assertEquals("state.jsonNull: NULL", getLogRow(logRow++)); | |||
Assert.assertEquals( | |||
"state.doubleArray: [1.7976931348623157e+308, 5e-324]", | |||
getLogRow(logRow++)); |
@@ -35,6 +35,13 @@ import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.shared.ui.label.ContentMode; | |||
import com.vaadin.tests.widgetset.server.SerializerTestExtension; | |||
import elemental.json.Json; | |||
import elemental.json.JsonBoolean; | |||
import elemental.json.JsonObject; | |||
import elemental.json.JsonString; | |||
import elemental.json.JsonType; | |||
import elemental.json.JsonValue; | |||
@Connect(SerializerTestExtension.class) | |||
public class SerializerTestConnector extends AbstractExtensionConnector { | |||
@@ -258,6 +265,27 @@ public class SerializerTestConnector extends AbstractExtensionConnector { | |||
rpc.sendDate(date); | |||
} | |||
@Override | |||
public void sendJson(JsonValue value1, JsonValue value2, | |||
JsonString string) { | |||
if (value1.getType() != JsonType.BOOLEAN) { | |||
throw new RuntimeException("Expected boolean, got " | |||
+ value1.toJson()); | |||
} | |||
if (value2.getType() != JsonType.NULL) { | |||
throw new RuntimeException("Expected null, got " | |||
+ value2.toJson()); | |||
} | |||
JsonObject returnObject = Json.createObject(); | |||
returnObject.put("b", !((JsonBoolean) value1).asBoolean()); | |||
returnObject.put("s", string); | |||
rpc.sendJson(returnObject, Json.createNull(), | |||
Json.create("value")); | |||
} | |||
@Override | |||
public void log(String message) { | |||
// Do nothing, used only in the other direction | |||
@@ -311,6 +339,11 @@ public class SerializerTestConnector extends AbstractExtensionConnector { | |||
rpc.log("state.doubleObjectValue: " + getState().doubleObjectValue); | |||
rpc.log("state.doubleArray: " + Arrays.toString(getState().doubleArray)); | |||
rpc.log("state.jsonNull: " + getState().jsonNull.getType().name()); | |||
rpc.log("state.jsonString: " | |||
+ ((JsonString) getState().jsonString).getString()); | |||
rpc.log("state.jsonBoolean: " + getState().jsonBoolean.getBoolean()); | |||
/* | |||
* TODO public double doubleValue; public Double DoubleValue; public | |||
* double[] doubleArray; ; |
@@ -26,6 +26,9 @@ import com.vaadin.shared.communication.ClientRpc; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
import com.vaadin.shared.ui.label.ContentMode; | |||
import elemental.json.JsonString; | |||
import elemental.json.JsonValue; | |||
@SuppressWarnings("javadoc") | |||
public interface SerializerTestRpc extends ServerRpc, ClientRpc { | |||
public void sendBoolean(boolean value, Boolean boxedValue, boolean[] array); | |||
@@ -82,5 +85,7 @@ public interface SerializerTestRpc extends ServerRpc, ClientRpc { | |||
public void sendDate(Date date); | |||
public void sendJson(JsonValue value1, JsonValue value2, JsonString string); | |||
public void log(String string); | |||
} |
@@ -24,6 +24,9 @@ import com.vaadin.shared.AbstractComponentState; | |||
import com.vaadin.shared.Connector; | |||
import com.vaadin.shared.ui.label.ContentMode; | |||
import elemental.json.JsonBoolean; | |||
import elemental.json.JsonValue; | |||
public class SerializerTestState extends AbstractComponentState { | |||
public boolean booleanValue; | |||
@@ -99,4 +102,8 @@ public class SerializerTestState extends AbstractComponentState { | |||
public BeanWithAbstractSuperclass beanWithAbstractSuperclass; | |||
public JsonValue jsonNull = null; | |||
public JsonValue jsonString = null; | |||
public JsonBoolean jsonBoolean = null; | |||
} |