diff --git a/sdk/pom.xml b/sdk/pom.xml
index ea59d88ad..456062718 100644
--- a/sdk/pom.xml
+++ b/sdk/pom.xml
@@ -127,6 +127,12 @@
grpc-inprocess
test
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson.version}
+ test
+
diff --git a/sdk/src/main/java/io/dapr/client/ObjectSerializer.java b/sdk/src/main/java/io/dapr/client/ObjectSerializer.java
index a131060b9..ce18ebc90 100644
--- a/sdk/src/main/java/io/dapr/client/ObjectSerializer.java
+++ b/sdk/src/main/java/io/dapr/client/ObjectSerializer.java
@@ -43,6 +43,10 @@ public class ObjectSerializer {
protected ObjectSerializer() {
}
+ protected ObjectMapper getObjectMapper() {
+ return OBJECT_MAPPER;
+ }
+
/**
* Serializes a given state object into byte array.
*
@@ -70,7 +74,7 @@ public class ObjectSerializer {
}
// Not string, not primitive, so it is a complex type: we use JSON for that.
- return OBJECT_MAPPER.writeValueAsBytes(state);
+ return getObjectMapper().writeValueAsBytes(state);
}
/**
@@ -83,7 +87,7 @@ public class ObjectSerializer {
* @throws IOException In case content cannot be deserialized.
*/
public T deserialize(byte[] content, TypeRef type) throws IOException {
- return deserialize(content, OBJECT_MAPPER.constructType(type.getType()));
+ return deserialize(content, getObjectMapper().constructType(type.getType()));
}
/**
@@ -96,7 +100,7 @@ public class ObjectSerializer {
* @throws IOException In case content cannot be deserialized.
*/
public T deserialize(byte[] content, Class clazz) throws IOException {
- return deserialize(content, OBJECT_MAPPER.constructType(clazz));
+ return deserialize(content, getObjectMapper().constructType(clazz));
}
private T deserialize(byte[] content, JavaType javaType) throws IOException {
@@ -138,7 +142,7 @@ public class ObjectSerializer {
}
}
- return OBJECT_MAPPER.readValue(content, javaType);
+ return getObjectMapper().readValue(content, javaType);
}
/**
@@ -149,7 +153,7 @@ public class ObjectSerializer {
* @throws IOException In case content cannot be parsed.
*/
public JsonNode parseNode(byte[] content) throws IOException {
- return OBJECT_MAPPER.readTree(content);
+ return getObjectMapper().readTree(content);
}
/**
diff --git a/sdk/src/main/java/io/dapr/serializer/CustomizableObjectSerializer.java b/sdk/src/main/java/io/dapr/serializer/CustomizableObjectSerializer.java
new file mode 100644
index 000000000..1838815d6
--- /dev/null
+++ b/sdk/src/main/java/io/dapr/serializer/CustomizableObjectSerializer.java
@@ -0,0 +1,23 @@
+package io.dapr.serializer;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.dapr.client.ObjectSerializer;
+
+public class CustomizableObjectSerializer extends ObjectSerializer implements DaprObjectSerializer {
+
+ private final ObjectMapper objectMapper;
+
+ public CustomizableObjectSerializer(ObjectMapper objectMapper) {
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public ObjectMapper getObjectMapper() {
+ return objectMapper;
+ }
+
+ @Override
+ public String getContentType() {
+ return "application/json";
+ }
+}
diff --git a/sdk/src/test/java/io/dapr/serializer/CustomObjectSerializerTest.java b/sdk/src/test/java/io/dapr/serializer/CustomObjectSerializerTest.java
new file mode 100644
index 000000000..d32ccbedd
--- /dev/null
+++ b/sdk/src/test/java/io/dapr/serializer/CustomObjectSerializerTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2021 The Dapr Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package io.dapr.serializer;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.google.common.base.Objects;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class CustomObjectSerializerTest {
+
+ private static final DaprObjectSerializer SERIALIZER =
+ new CustomizableObjectSerializer(new ObjectMapper()
+ .registerModule(new JavaTimeModule())
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS));
+
+ public static class ObjectForTesting implements Serializable {
+ private ZonedDateTime time;
+
+ public ZonedDateTime getTime() {
+ return time;
+ }
+
+ public void setTime(ZonedDateTime time) {
+ this.time = time;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ObjectForTesting that = (ObjectForTesting) o;
+ return Objects.equal(time, that.time);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(time);
+ }
+ }
+
+ @Test
+ public void serializeObjectForTesting() {
+ ObjectForTesting obj = new ObjectForTesting();
+ obj.setTime(ZonedDateTime.of(1900, 1, 1, 1, 1, 0, 0, ZoneId.of("UTC")));
+ String expectedResult =
+ "{\"time\":\"1900-01-01T01:01:00Z\"}";
+
+ String serializedValue;
+ try {
+ serializedValue = new String(SERIALIZER.serialize(obj));
+ assertEquals(expectedResult, serializedValue,
+ "FOUND:[[" + serializedValue + "]] \n but was EXPECTING: [[" + expectedResult + "]]");
+ } catch (IOException exception) {
+ fail(exception.getMessage());
+ }
+ }
+}