diff --git a/json-modules/gson-4/gson-module-opens/pom.xml b/json-modules/gson-4/gson-module-opens/pom.xml
new file mode 100644
index 000000000000..2be112fa19b8
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/pom.xml
@@ -0,0 +1,15 @@
+
+
+ 4.0.0
+
+
+ com.baeldung
+ gson-4
+ 1.0.0-SNAPSHOT
+
+
+ gson-module-opens
+ jar
+
+
diff --git a/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/ConferencePojo.java b/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/ConferencePojo.java
new file mode 100644
index 000000000000..e10425669823
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/ConferencePojo.java
@@ -0,0 +1,23 @@
+package gson.exception;
+
+public class ConferencePojo {
+
+ private String name;
+ private int numberOfParticipants;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getNumberOfParticipants() {
+ return numberOfParticipants;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setNumberOfParticipants(int numberOfParticipants) {
+ this.numberOfParticipants = numberOfParticipants;
+ }
+}
diff --git a/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/ConferencePojoWithDate.java b/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/ConferencePojoWithDate.java
new file mode 100644
index 000000000000..88916ccd6f3b
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/ConferencePojoWithDate.java
@@ -0,0 +1,34 @@
+package gson.exception;
+
+import java.time.LocalDate;
+
+public class ConferencePojoWithDate {
+
+ private String name;
+ private int numberOfParticipants;
+ private LocalDate conferenceStart;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getNumberOfParticipants() {
+ return numberOfParticipants;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setNumberOfParticipants(int numberOfParticipants) {
+ this.numberOfParticipants = numberOfParticipants;
+ }
+
+ public LocalDate getConferenceStart() {
+ return conferenceStart;
+ }
+
+ public void setConferenceStart(LocalDate conferenceStart) {
+ this.conferenceStart = conferenceStart;
+ }
+}
diff --git a/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/GsonModuleMain.java b/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/GsonModuleMain.java
new file mode 100644
index 000000000000..efc7faa67a8e
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/main/java/gson/exception/GsonModuleMain.java
@@ -0,0 +1,36 @@
+package gson.exception;
+
+import java.time.LocalDate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+
+public class GsonModuleMain {
+
+ static Logger log = LoggerFactory.getLogger(GsonModuleMain.class);
+
+ public static void main(String[] args) {
+
+ String moduleName = GsonModuleMain.class.getModule()
+ .getName();
+
+ if (moduleName == null) {
+ log.info("Mode: [ Class Path ] (Class in the Unnamed Module)");
+ } else {
+ log.info("Mode: [ Module Path ] - Module name: " + moduleName);
+ }
+ LocalDate excpectedDate = LocalDate.of(2026, 8, 17);
+ Gson gson = new Gson();
+ String json = "{\"name\":\"Java Conference\"}";
+
+ try {
+ ConferencePojo pojo = gson.fromJson(json, ConferencePojo.class);
+ log.info("Deserialization successful! Object " + pojo);
+ } catch (Exception e) {
+ log.info("Expected exception caught!");
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/json-modules/gson-4/gson-module-opens/src/main/java/module-info.java b/json-modules/gson-4/gson-module-opens/src/main/java/module-info.java
new file mode 100644
index 000000000000..073dbc9dfa81
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/main/java/module-info.java
@@ -0,0 +1,9 @@
+module gson.exception {
+
+ requires com.google.gson;
+ requires org.slf4j;
+
+ opens gson.exception to com.google.gson;
+
+ exports gson.exception;
+}
\ No newline at end of file
diff --git a/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/ModularOpensGsonUnitTest.java b/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/ModularOpensGsonUnitTest.java
new file mode 100644
index 000000000000..eaea47f71452
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/ModularOpensGsonUnitTest.java
@@ -0,0 +1,26 @@
+package gson.exception;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.Gson;
+
+class ModularOpensGsonUnitTest {
+
+ @Test
+ void givenModularAndOpens_whenDeserializingPojo_thenSuccess() {
+ String json = "{\"name\":\"Java Conference\",\"numberOfParticipants\":150}";
+ Gson gson = new Gson();
+
+ ConferencePojo result = assertDoesNotThrow(() -> {
+ return gson.fromJson(json, ConferencePojo.class);
+ });
+
+ assertNotNull(result);
+ assertEquals("Java Conference", result.getName());
+ }
+
+}
diff --git a/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/ModularStructureConfirmationUnitTest.java b/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/ModularStructureConfirmationUnitTest.java
new file mode 100644
index 000000000000..dc31e51aa561
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/ModularStructureConfirmationUnitTest.java
@@ -0,0 +1,17 @@
+package gson.exception;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class ModularStructureConfirmationUnitTest {
+
+ @Test
+ void whenModular_thenModuleIsNamed() {
+ Module module = this.getClass()
+ .getModule();
+
+ assertTrue(module.isNamed(), "Test run on Classpath, JPMS strong encapsulation won't work!");
+ }
+
+}
diff --git a/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/PojoWithLocalDateUnitTest.java b/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/PojoWithLocalDateUnitTest.java
new file mode 100644
index 000000000000..24d16ad7c13c
--- /dev/null
+++ b/json-modules/gson-4/gson-module-opens/src/test/java/gson/exception/PojoWithLocalDateUnitTest.java
@@ -0,0 +1,45 @@
+package gson.exception;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.time.LocalDate;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+class PojoWithLocalDateUnitTest {
+
+ @Test
+ void whenObjectDateFormat_thenSuccessfulDeserialization() {
+ String correctJson = "{"
+ + "\"name\":\"Java Conference\","
+ + "\"numberOfParticipants\":500,"
+ + "\"conferenceStart\":{\"year\":2026,\"month\":8,\"day\":17}"
+ + "}";
+
+ Gson gson = new Gson();
+ ConferencePojoWithDate result = gson.fromJson(correctJson, ConferencePojoWithDate.class);
+
+ LocalDate excpectedDate = LocalDate.of(2026, 8, 17);
+ assertEquals(excpectedDate, result.getConferenceStart(), "Date should be the same as in JSON");
+ }
+
+ @Test
+ void whenISOTextFormat_thenJsonSyntaxException() {
+
+ String wrongDateInJson = "{"
+ + "\"name\":\"Java Conference\","
+ + "\"numberOfParticipants\":500,"
+ + "\"conferenceStart\":\"2026-08-17\""
+ + "}";
+
+ Gson gson = new Gson();
+ assertThrows(JsonSyntaxException.class, () -> {
+ gson.fromJson(wrongDateInJson, ConferencePojoWithDate.class);
+ }, "JsonSyntaxException was expected due to an incompatible date format");
+
+ }
+}
diff --git a/json-modules/gson-4/gson-module/pom.xml b/json-modules/gson-4/gson-module/pom.xml
new file mode 100644
index 000000000000..def51e551bff
--- /dev/null
+++ b/json-modules/gson-4/gson-module/pom.xml
@@ -0,0 +1,14 @@
+
+
+ 4.0.0
+
+
+ com.baeldung
+ gson-4
+ 1.0.0-SNAPSHOT
+
+
+ gson-module
+ jar
+
diff --git a/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojo.java b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojo.java
new file mode 100644
index 000000000000..e10425669823
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojo.java
@@ -0,0 +1,23 @@
+package gson.exception;
+
+public class ConferencePojo {
+
+ private String name;
+ private int numberOfParticipants;
+
+ public String getName() {
+ return name;
+ }
+
+ public int getNumberOfParticipants() {
+ return numberOfParticipants;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setNumberOfParticipants(int numberOfParticipants) {
+ this.numberOfParticipants = numberOfParticipants;
+ }
+}
diff --git a/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojoAdapter.java b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojoAdapter.java
new file mode 100644
index 000000000000..7973212d3413
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojoAdapter.java
@@ -0,0 +1,40 @@
+package gson.exception;
+
+import java.io.IOException;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+public class ConferencePojoAdapter extends TypeAdapter {
+
+ @Override
+ public void write(JsonWriter out, ConferencePojo value) throws IOException {
+ throw new UnsupportedOperationException("This adapter is for deserialization only!");
+ }
+
+ @Override
+ public ConferencePojo read(JsonReader in) throws IOException {
+ String name = null;
+ int numberOfParticipants = 0;
+
+ in.beginObject();
+ while (in.hasNext()) {
+ String key = in.nextName();
+ if ("name".equals(key)) {
+ name = in.nextString();
+ } else if ("numberOfParticipants".equals(key)) {
+ numberOfParticipants = in.nextInt();
+ } else {
+ in.skipValue();
+ }
+ }
+ in.endObject();
+
+ ConferencePojo result = new ConferencePojo();
+ result.setName(name);
+ result.setNumberOfParticipants(numberOfParticipants);
+
+ return result;
+ }
+}
diff --git a/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojoPublic.java b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojoPublic.java
new file mode 100644
index 000000000000..2c91707bb67d
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferencePojoPublic.java
@@ -0,0 +1,7 @@
+package gson.exception;
+
+public class ConferencePojoPublic {
+
+ public String name;
+ public int numberOfParticipants;
+}
diff --git a/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferenceRecord.java b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferenceRecord.java
new file mode 100644
index 000000000000..efe6128c7c35
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/main/java/gson/exception/ConferenceRecord.java
@@ -0,0 +1,5 @@
+package gson.exception;
+
+public record ConferenceRecord(String name, int numberOfParticipants) {
+
+}
diff --git a/json-modules/gson-4/gson-module/src/main/java/gson/exception/GsonModuleMain.java b/json-modules/gson-4/gson-module/src/main/java/gson/exception/GsonModuleMain.java
new file mode 100644
index 000000000000..c2c0dae8c204
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/main/java/gson/exception/GsonModuleMain.java
@@ -0,0 +1,34 @@
+package gson.exception;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+
+public class GsonModuleMain {
+
+ static Logger log = LoggerFactory.getLogger(GsonModuleMain.class);
+
+ public static void main(String[] args) {
+
+ String moduleName = GsonModuleMain.class.getModule()
+ .getName();
+
+ if (moduleName == null) {
+ log.info("Mode: [ Class Path ] (Class in the Unnamed Module)");
+ } else {
+ log.info("Mode: [ Module Path ] - Module name: " + moduleName);
+ }
+
+ Gson gson = new Gson();
+ String json = "{\"name\":\"Java Conference\"}";
+
+ try {
+ ConferencePojo pojo = gson.fromJson(json, ConferencePojo.class);
+ log.info("Deserialization successful! Object " + pojo);
+ } catch (Exception e) {
+ log.info("Expected exception caught!");
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/json-modules/gson-4/gson-module/src/main/java/module-info.java b/json-modules/gson-4/gson-module/src/main/java/module-info.java
new file mode 100644
index 000000000000..9401a2cc7bc5
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/main/java/module-info.java
@@ -0,0 +1,7 @@
+module gson.exception {
+
+ requires com.google.gson;
+ requires org.slf4j;
+
+ exports gson.exception;
+}
diff --git a/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularGsonUnitTest.java b/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularGsonUnitTest.java
new file mode 100644
index 000000000000..5fc9e79b4e91
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularGsonUnitTest.java
@@ -0,0 +1,50 @@
+package gson.exception;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonIOException;
+
+public class ModularGsonUnitTest {
+
+ @Test
+ void givenModularAndExportedPackage_whenDeserializingPojo_thenJsonIOException() {
+ String json = "{\"name\":\"Java Conference\",\"numberOfParticipants\":150}";
+ Gson gson = new Gson();
+
+ assertThrows(JsonIOException.class, () -> {
+ gson.fromJson(json, ConferencePojo.class);
+ });
+ }
+
+ @Test
+ void givenModularAndExportedPackage_whenDeserializingRecord_thenSuccess() {
+ String json = "{\"name\":\"Java Conference\",\"numberOfParticipants\":150}";
+ Gson gson = new Gson();
+
+ ConferenceRecord result = assertDoesNotThrow(() -> {
+ return gson.fromJson(json, ConferenceRecord.class);
+ });
+
+ assertNotNull(result);
+ assertEquals("Java Conference", result.name());
+ }
+
+ @Test
+ void givenModularAndExportedPackage_whenDeserializingPublicPojo_thenSuccess() {
+ String json = "{\"name\":\"Java Conference\",\"numberOfParticipants\":150}";
+ Gson gson = new Gson();
+
+ ConferencePojoPublic result = assertDoesNotThrow(() -> {
+ return gson.fromJson(json, ConferencePojoPublic.class);
+ });
+
+ assertNotNull(result);
+ assertEquals("Java Conference", result.name);
+ }
+}
diff --git a/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularGsonWithAdapterUnitTest.java b/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularGsonWithAdapterUnitTest.java
new file mode 100644
index 000000000000..80b03af6cd6a
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularGsonWithAdapterUnitTest.java
@@ -0,0 +1,26 @@
+package gson.exception;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public class ModularGsonWithAdapterUnitTest {
+
+ @Test
+ void whenAdapterForPojo_thenSuccess() {
+ Gson gson = new GsonBuilder()
+ .registerTypeAdapter(ConferencePojo.class, new ConferencePojoAdapter())
+ .create();
+
+ String jsonInput = "{\"name\":\"Java Conference\", \"numberOfParticipants\":100}";
+
+ ConferencePojo result = gson.fromJson(jsonInput, ConferencePojo.class);
+
+ assertNotNull(result);
+ assertEquals("Java Conference", result.getName());
+ }
+}
diff --git a/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularStructureConfirmationUnitTest.java b/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularStructureConfirmationUnitTest.java
new file mode 100644
index 000000000000..db9e41ac851b
--- /dev/null
+++ b/json-modules/gson-4/gson-module/src/test/java/gson/exception/ModularStructureConfirmationUnitTest.java
@@ -0,0 +1,16 @@
+package gson.exception;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+class ModularStructureConfirmationUnitTest {
+
+ @Test
+ void whenModular_thenModuleIsNamed() {
+ Module module = this.getClass()
+ .getModule();
+ assertTrue(module.isNamed(), "Test run on Classpath, JPMS strong encapsulation won't work!");
+ }
+
+}
diff --git a/json-modules/gson-4/pom.xml b/json-modules/gson-4/pom.xml
new file mode 100644
index 000000000000..bea764b429ba
--- /dev/null
+++ b/json-modules/gson-4/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+ gson-4
+ pom
+ gson-4
+
+
+ json-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+
+ gson-module
+ gson-module-opens
+
+
+
+ 2.14.0
+ 17
+
+
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
+
+
+
+
diff --git a/json-modules/pom.xml b/json-modules/pom.xml
index 59f7feebc6cf..3751b3e91d94 100644
--- a/json-modules/pom.xml
+++ b/json-modules/pom.xml
@@ -25,6 +25,7 @@
gson
gson-2
gson-3
+ gson-4