summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorOlli Tietäväinen <ollit@vaadin.com>2019-02-22 10:50:51 +0200
committerSun Zhe <31067185+ZheSun88@users.noreply.github.com>2019-02-22 10:50:51 +0200
commit9d5bdaf89bd173bec7364d591377ca17bb5bb91d (patch)
treecaa481e8d5f29f24be6f11ffd1cac4dfe7f9d887 /server
parentc79dca4391bff459f090102447c5502089bf9fc7 (diff)
downloadvaadin-framework-9d5bdaf89bd173bec7364d591377ca17bb5bb91d.tar.gz
vaadin-framework-9d5bdaf89bd173bec7364d591377ca17bb5bb91d.zip
Custom serializers accessors (#10658)
* add accessor methods for CUSTOM_SERIALIZERS in JsonCodec * javadoc * removed removeCustomSerializer method, renamed putCustomSerializer to addCustomSerializer, added sanity checks and JavaDocs * refactored addCustomJsonSerializer to set, added test UI * move enums to be parsed after custom serializers * move adding custom serializer to static block * throw an exception if multiple serializers are registered for class * updated javadocs * changed CustomJSONSerializerTest to a SingleBrowserTest * moved CustomJSONSerializerTest to server/ and it's now not a browser test * removed CustomJSONSerializerTest
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/server/JsonCodec.java65
-rw-r--r--server/src/test/java/com/vaadin/server/CustomJSONSerializerTest.java52
2 files changed, 111 insertions, 6 deletions
diff --git a/server/src/main/java/com/vaadin/server/JsonCodec.java b/server/src/main/java/com/vaadin/server/JsonCodec.java
index eeb27b0e5a..877fc6192f 100644
--- a/server/src/main/java/com/vaadin/server/JsonCodec.java
+++ b/server/src/main/java/com/vaadin/server/JsonCodec.java
@@ -325,14 +325,14 @@ public class JsonCodec implements Serializable {
} else if (JsonValue.class
.isAssignableFrom(getClassForType(targetType))) {
return value;
- } else if (Enum.class.isAssignableFrom(getClassForType(targetType))) {
- Class<?> classForType = getClassForType(targetType);
- return decodeEnum(classForType.asSubclass(Enum.class),
- (JsonString) value);
} else if (CUSTOM_SERIALIZERS
.containsKey(getClassForType(targetType))) {
return CUSTOM_SERIALIZERS.get(getClassForType(targetType))
.deserialize(targetType, value, connectorTracker);
+ } else if (Enum.class.isAssignableFrom(getClassForType(targetType))) {
+ Class<?> classForType = getClassForType(targetType);
+ return decodeEnum(classForType.asSubclass(Enum.class),
+ (JsonString) value);
} else {
return decodeObject(targetType, (JsonObject) value,
connectorTracker);
@@ -445,6 +445,59 @@ public class JsonCodec implements Serializable {
throw new JsonException("Unknown type " + transportType);
}
+ /**
+ * Set a custom JSONSerializer for a specific Class. Existence of custom
+ * serializers is checked after basic types (Strings, Booleans, Numbers,
+ * Characters), Collections and Maps, so setting custom serializers for
+ * these won't have any effect.
+ * <p>
+ * To remove a previously set serializer, call this method with the second
+ * parameter set to {@code null}.
+ * <p>
+ * Custom serializers should only be added from static initializers or other
+ * places that are guaranteed to run only once. Trying to add a serializer
+ * to a class that already has one will cause an exception.
+ * <p>
+ * Warning: removing existing custom serializers may lead into unexpected
+ * behavior in components that expect the customized data. The framework's
+ * custom serializers are loaded in the static initializer block of this
+ * class.
+ *
+ * @see DateSerializer
+ * @throws IllegalArgumentException
+ * Thrown if parameter clazz is null.
+ * @throws IllegalStateException
+ * Thrown if serializer for parameter clazz is already
+ * registered and parameter jsonSerializer is not null.
+ * @param clazz
+ * The target class.
+ * @param jsonSerializer
+ * Custom JSONSerializer to add. If {@code null}, remove custom
+ * serializer from class clazz.
+ */
+ public static <TYPE> void setCustomSerializer(Class<TYPE> clazz,
+ JSONSerializer<TYPE> jsonSerializer) {
+ if (clazz == null) {
+ throw new IllegalArgumentException(
+ "Cannot add serializer for null");
+ }
+ if (jsonSerializer == null) {
+ CUSTOM_SERIALIZERS.remove(clazz);
+ } else {
+ if (CUSTOM_SERIALIZERS.containsKey(clazz)) {
+ String err = String.format(
+ "Class %s already has a custom serializer. "
+ + "This exception can be thrown if you try to "
+ + "add a serializer from a non-static context. "
+ + "Try using a static block instead.",
+ clazz.getName());
+ throw new IllegalStateException(err);
+ }
+ CUSTOM_SERIALIZERS.put(clazz, jsonSerializer);
+ }
+
+ }
+
private static UidlValue decodeUidlValue(JsonArray encodedJsonValue,
ConnectorTracker connectorTracker) {
String type = encodedJsonValue.getString(0);
@@ -668,10 +721,10 @@ public class JsonCodec implements Serializable {
}
// Connectors are simply serialized as ID.
toReturn = Json.create(((Connector) value).getConnectorId());
- } else if (value instanceof Enum) {
- toReturn = Json.create(((Enum<?>) value).name());
} else if (CUSTOM_SERIALIZERS.containsKey(value.getClass())) {
toReturn = serializeJson(value, connectorTracker);
+ } else if (value instanceof Enum) {
+ toReturn = Json.create(((Enum<?>) value).name());
} else if (valueType instanceof GenericArrayType) {
toReturn = encodeArrayContents(
((GenericArrayType) valueType).getGenericComponentType(),
diff --git a/server/src/test/java/com/vaadin/server/CustomJSONSerializerTest.java b/server/src/test/java/com/vaadin/server/CustomJSONSerializerTest.java
new file mode 100644
index 0000000000..0c8b69fe62
--- /dev/null
+++ b/server/src/test/java/com/vaadin/server/CustomJSONSerializerTest.java
@@ -0,0 +1,52 @@
+package com.vaadin.server;
+
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Type;
+
+import org.junit.Test;
+
+import com.vaadin.server.communication.JSONSerializer;
+import com.vaadin.ui.ConnectorTracker;
+
+import elemental.json.JsonValue;
+
+public class CustomJSONSerializerTest {
+
+ public static class Foo {
+
+ }
+
+ public static class FooSerializer implements JSONSerializer<Foo> {
+
+ @Override
+ public Foo deserialize(Type type, JsonValue jsonValue,
+ ConnectorTracker connectorTracker) {
+ return null;
+ }
+
+ @Override
+ public JsonValue serialize(Foo value,
+ ConnectorTracker connectorTracker) {
+ return null;
+ }
+
+ }
+
+ @Test
+ public void testMultipleRegistration() {
+ boolean thrown = false;
+ try {
+ JsonCodec.setCustomSerializer(Foo.class, new FooSerializer());
+ JsonCodec.setCustomSerializer(Foo.class, new FooSerializer());
+ } catch (IllegalStateException ise) {
+ thrown = true;
+ } finally {
+ JsonCodec.setCustomSerializer(Foo.class, null);
+ }
+ assertTrue("Multiple serializer registrations for one class "
+ + "should throw an IllegalStateException", thrown);
+
+ }
+
+}