diff --git a/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/DtoFactory.java b/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/DtoFactory.java index 1c034e9035..e738b10772 100644 --- a/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/DtoFactory.java +++ b/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/DtoFactory.java @@ -22,6 +22,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonSyntaxException; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; +import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; @@ -511,6 +512,8 @@ public final class DtoFactory { builder.registerTypeHierarchyAdapter(Map.class, new NullOrEmptyMapAdapter()); } + builder.registerTypeAdapterFactory(new SerializableInterfaceAdapterFactory()); + return builder.create(); } } diff --git a/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/SerializableInterfaceAdapterFactory.java b/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/SerializableInterfaceAdapterFactory.java new file mode 100644 index 0000000000..1899ce0f4c --- /dev/null +++ b/core/che-core-api-dto/src/main/java/org/eclipse/che/dto/server/SerializableInterfaceAdapterFactory.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.dto.server; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.Serializable; + +/** + * This adapter is required for fields of {@link java.io.Serializable} type to be treated as {@link + * Object} + */ +public class SerializableInterfaceAdapterFactory implements TypeAdapterFactory { + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (Serializable.class.equals(type.getRawType())) { + return (TypeAdapter) new SerializableAdapter(gson.getAdapter(Object.class)); + } + return null; + } + + private static class SerializableAdapter extends TypeAdapter { + + TypeAdapter objectAdapter; + + public SerializableAdapter(TypeAdapter objectAdapter) { + this.objectAdapter = objectAdapter; + } + + @Override + public void write(JsonWriter out, Object value) throws IOException { + objectAdapter.write(out, value); + } + + @Override + public Object read(JsonReader in) throws IOException { + JsonToken token = in.peek(); + if (token.equals(JsonToken.NUMBER)) { + try { + return in.nextLong(); + } catch (NumberFormatException e) { + return in.nextDouble(); + } + } + return objectAdapter.read(in); + } + } +} diff --git a/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/ServerDtoTest.java b/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/ServerDtoTest.java index 20c67eb9cb..6d71bb4b62 100644 --- a/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/ServerDtoTest.java +++ b/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/ServerDtoTest.java @@ -31,6 +31,7 @@ import org.eclipse.che.dto.definitions.DTOHierarchy.GrandchildDto; import org.eclipse.che.dto.definitions.DtoWithAny; import org.eclipse.che.dto.definitions.DtoWithDelegate; import org.eclipse.che.dto.definitions.DtoWithFieldNames; +import org.eclipse.che.dto.definitions.DtoWithSerializable; import org.eclipse.che.dto.definitions.SimpleDto; import org.eclipse.che.dto.definitions.model.Model; import org.eclipse.che.dto.definitions.model.ModelComponentDto; @@ -435,4 +436,36 @@ public class ServerDtoTest { public void shouldThrowExceptionWhenInterfaceIsNotAnnotatedAsDto() { DtoFactory.newDto(DTOHierarchy.GrandchildWithoutDto.class); } + + @Test + public void checkDtoDeserializationWithSerializableFields() { + final int fooId = 1; + final String fooString = "some string"; + final long fooLong = 1234514362645634611L; + final double fooDouble = 1.2345; + final double fooRoundingDouble = 6.00; + + JsonObject jsonMap = new JsonObject(); + jsonMap.add("fooLong", new JsonPrimitive(fooLong)); + jsonMap.add("fooBoolean", new JsonPrimitive(true)); + jsonMap.add("fooDouble", new JsonPrimitive(fooDouble)); + jsonMap.add("fooRoundingDouble", new JsonPrimitive(fooRoundingDouble)); + jsonMap.add("fooString", new JsonPrimitive(fooString)); + + JsonObject json = new JsonObject(); + json.add("id", new JsonPrimitive(fooId)); + json.add("object", new JsonPrimitive(fooString)); + json.add("objectMap", jsonMap); + + DtoWithSerializable dto = + dtoFactory.createDtoFromJson(json.toString(), DtoWithSerializable.class); + + assertEquals(dto.getId(), fooId); + assertEquals(dto.getObject(), fooString); + assertEquals(dto.getObjectMap().get("fooLong"), fooLong); + assertEquals(dto.getObjectMap().get("fooBoolean"), true); + assertEquals(dto.getObjectMap().get("fooDouble"), fooDouble); + assertEquals(dto.getObjectMap().get("fooString"), fooString); + assertEquals(dto.getObjectMap().get("fooRoundingDouble"), Math.round(fooRoundingDouble)); + } } diff --git a/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/definitions/DtoWithSerializable.java b/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/definitions/DtoWithSerializable.java new file mode 100644 index 0000000000..332c74ff4c --- /dev/null +++ b/core/che-core-api-dto/src/test/java/org/eclipse/che/dto/definitions/DtoWithSerializable.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.dto.definitions; + +import java.io.Serializable; +import java.util.Map; +import org.eclipse.che.dto.shared.DTO; + +/** DTO for testing serialization of fields with {@link java.io.Serializable} type */ +@DTO +public interface DtoWithSerializable { + int getId(); + + DtoWithSerializable withId(int id); + + Serializable getObject(); + + void setObject(Serializable object); + + DtoWithSerializable withObject(Serializable object); + + Map getObjectMap(); + + void setObjectMap(Map map); + + DtoWithSerializable withObjectMap(Map map); +}