You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2026/04/29 12:52:32 UTC
(geode) branch develop updated: GEODE-8256: Support Java 8 types in PdxInstanceImpl typed JSON deserialization (#7998)
This is an automated email from the ASF dual-hosted git repository.
JinwooHwang pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new 42131c7d16 GEODE-8256: Support Java 8 types in PdxInstanceImpl typed JSON deserialization (#7998)
42131c7d16 is described below
commit 42131c7d16a464e90f032a1bfbf90fa81e2e73ff
Author: daidai <da...@gmail.com>
AuthorDate: Wed Apr 29 20:52:25 2026 +0800
GEODE-8256: Support Java 8 types in PdxInstanceImpl typed JSON deserialization (#7998)
---
geode-core/build.gradle | 2 +
.../apache/geode/pdx/JSONFormatterJUnitTest.java | 158 +++++++++++++++++++++
.../apache/geode/pdx/internal/PdxInstanceImpl.java | 4 +
3 files changed, 164 insertions(+)
diff --git a/geode-core/build.gradle b/geode-core/build.gradle
index 4188aaea93..16a0ee8f55 100755
--- a/geode-core/build.gradle
+++ b/geode-core/build.gradle
@@ -222,6 +222,8 @@ dependencies {
//Jackson databind is used in gfsh, and also in pdx
implementation('com.fasterxml.jackson.core:jackson-databind')
+ implementation('com.fasterxml.jackson.datatype:jackson-datatype-jdk8')
+ implementation('com.fasterxml.jackson.datatype:jackson-datatype-jsr310')
//Commons validator is used to validate inet addresses in membership
implementation('commons-validator:commons-validator')
diff --git a/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java b/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
index 2b5fecfa74..45beee029c 100755
--- a/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
+++ b/geode-core/src/integrationTest/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
@@ -19,10 +19,15 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.text.SimpleDateFormat;
+import java.time.LocalDate;
import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -152,6 +157,44 @@ public class JSONFormatterJUnitTest {
actualTestObject);
}
+ @Test
+ public void verifyJsonToPdxInstanceConversionWithOptionalField() {
+ OptionalValueHolder expectedValue = new OptionalValueHolder(Optional.of("typed-json"));
+ String json = jsonWithType(OptionalValueHolder.class, "\"optionalValue\":\"typed-json\"");
+
+ PdxInstance pdxInstance = JSONFormatter.fromJSON(json);
+ Object actualValue = pdxInstance.getObject();
+
+ assertEquals(OptionalValueHolder.class, actualValue.getClass());
+ assertEquals(expectedValue, actualValue);
+ }
+
+ @Test
+ public void verifyJsonToPdxInstanceConversionWithLocalDateField() {
+ LocalDateValueHolder expectedValue = new LocalDateValueHolder(LocalDate.of(2026, 3, 29));
+ String json = jsonWithType(LocalDateValueHolder.class, "\"localDateValue\":\"2026-03-29\"");
+
+ PdxInstance pdxInstance = JSONFormatter.fromJSON(json);
+ Object actualValue = pdxInstance.getObject();
+
+ assertEquals(LocalDateValueHolder.class, actualValue.getClass());
+ assertEquals(expectedValue, actualValue);
+ }
+
+ @Test
+ public void geodePdxInstanceObjectMapperCanDeserializeJava8Types() {
+ TimedType expectedValue = new TimedType(LocalDate.of(2026, 3, 29));
+
+ ObjectNode objectNode = java8ObjectMapper().valueToTree(expectedValue);
+ objectNode.put("@type", TimedType.class.getName());
+
+ PdxInstance pdxInstance = JSONFormatter.fromJSON(objectNode.toString());
+ Object actualValue = pdxInstance.getObject();
+
+ assertEquals(TimedType.class, actualValue.getClass());
+ assertEquals(expectedValue, actualValue);
+ }
+
/**
* this test validates json document, where field has value and null Then it verifies we create
* only one pdx type id for that
@@ -220,4 +263,119 @@ public class JSONFormatterJUnitTest {
System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "false");
}
}
+
+ private static String jsonWithType(Class<?> type, String fields) {
+ return "{\"@type\":\"" + type.getName() + "\"," + fields + "}";
+ }
+
+ private static ObjectMapper java8ObjectMapper() {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new JavaTimeModule());
+ return objectMapper;
+ }
+
+ public static class OptionalValueHolder {
+ private Optional<String> optionalValue;
+
+ public OptionalValueHolder() {}
+
+ OptionalValueHolder(Optional<String> optionalValue) {
+ this.optionalValue = optionalValue;
+ }
+
+ public Optional<String> getOptionalValue() {
+ return optionalValue;
+ }
+
+ public void setOptionalValue(Optional<String> optionalValue) {
+ this.optionalValue = optionalValue;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (!(object instanceof OptionalValueHolder)) {
+ return false;
+ }
+ OptionalValueHolder that = (OptionalValueHolder) object;
+ return Objects.equals(optionalValue, that.optionalValue);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(optionalValue);
+ }
+ }
+
+ public static class LocalDateValueHolder {
+ private LocalDate localDateValue;
+
+ public LocalDateValueHolder() {}
+
+ LocalDateValueHolder(LocalDate localDateValue) {
+ this.localDateValue = localDateValue;
+ }
+
+ public LocalDate getLocalDateValue() {
+ return localDateValue;
+ }
+
+ public void setLocalDateValue(LocalDate localDateValue) {
+ this.localDateValue = localDateValue;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (!(object instanceof LocalDateValueHolder)) {
+ return false;
+ }
+ LocalDateValueHolder that = (LocalDateValueHolder) object;
+ return Objects.equals(localDateValue, that.localDateValue);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(localDateValue);
+ }
+ }
+
+ public static class TimedType {
+ private LocalDate localDate;
+
+ public TimedType() {}
+
+ TimedType(LocalDate localDate) {
+ this.localDate = localDate;
+ }
+
+ public LocalDate getLocalDate() {
+ return localDate;
+ }
+
+ public void setLocalDate(LocalDate localDate) {
+ this.localDate = localDate;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (!(object instanceof TimedType)) {
+ return false;
+ }
+ TimedType timedType = (TimedType) object;
+ return Objects.equals(localDate, timedType.localDate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(localDate);
+ }
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/internal/PdxInstanceImpl.java b/geode-core/src/main/java/org/apache/geode/pdx/internal/PdxInstanceImpl.java
index 5170d9eb08..bbcb8cc72d 100644
--- a/geode-core/src/main/java/org/apache/geode/pdx/internal/PdxInstanceImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/pdx/internal/PdxInstanceImpl.java
@@ -28,6 +28,8 @@ import java.util.TreeSet;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.commons.lang3.StringUtils;
import org.apache.geode.InternalGemFireException;
@@ -71,6 +73,8 @@ public class PdxInstanceImpl extends PdxReaderImpl implements InternalPdxInstanc
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES,
true);
+ mapper.registerModule(new Jdk8Module());
+ mapper.registerModule(new JavaTimeModule());
return mapper;
}