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;
   }