diff options
author | Olli Tietäväinen <ollit@vaadin.com> | 2019-02-22 10:50:51 +0200 |
---|---|---|
committer | Sun Zhe <31067185+ZheSun88@users.noreply.github.com> | 2019-02-22 10:50:51 +0200 |
commit | 9d5bdaf89bd173bec7364d591377ca17bb5bb91d (patch) | |
tree | caa481e8d5f29f24be6f11ffd1cac4dfe7f9d887 /server | |
parent | c79dca4391bff459f090102447c5502089bf9fc7 (diff) | |
download | vaadin-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.java | 65 | ||||
-rw-r--r-- | server/src/test/java/com/vaadin/server/CustomJSONSerializerTest.java | 52 |
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); + + } + +} |