This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 92cbb3f39c minor refactor: junit5 and doco improvements (typed 
checking section)
92cbb3f39c is described below

commit 92cbb3f39ce6446216cff8c563c1b7316baa31c5
Author: Paul King <[email protected]>
AuthorDate: Mon Apr 13 15:37:01 2026 +1000

    minor refactor: junit5 and doco improvements (typed checking section)
---
 .../groovy-json/src/spec/doc/json-userguide.adoc   | 44 ++++++++++++++
 .../groovy-json/src/spec/test/json/JsonTest.groovy | 67 +++++++++++++++++++++-
 2 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/subprojects/groovy-json/src/spec/doc/json-userguide.adoc 
b/subprojects/groovy-json/src/spec/doc/json-userguide.adoc
index 2c12d4efa2..6700231df0 100644
--- a/subprojects/groovy-json/src/spec/doc/json-userguide.adoc
+++ b/subprojects/groovy-json/src/spec/doc/json-userguide.adoc
@@ -217,6 +217,50 @@ 
include::../test/json/JsonTest.groovy[tags=pretty_print,indent=0]
 `prettyPrint` takes a `String` as single parameter; therefore, it can be 
applied on arbitrary JSON `String` instances, not only the result of
 `JsonOutput.toJson`.
 
+== Typed JSON Parsing
+
+Since `JsonSlurper` parses JSON values into their natural JVM types
+(`Integer`, `BigDecimal`, `Boolean`, `List`, `Map`), Groovy's built-in
+`as` coercion works well for converting parsed JSON directly into
+typed objects -- no additional dependencies are required:
+
+[source,groovy]
+----
+include::../test/json/JsonTest.groovy[tags=typed_classes,indent=0]
+----
+
+[source,groovy]
+----
+include::../test/json/JsonTest.groovy[tags=typed_coercion,indent=0]
+----
+
+Nested objects are automatically coerced:
+
+[source,groovy]
+----
+include::../test/json/JsonTest.groovy[tags=typed_coercion_nested,indent=0]
+----
+
+Enum values are also handled:
+
+[source,groovy]
+----
+include::../test/json/JsonTest.groovy[tags=typed_coercion_enum,indent=0]
+----
+
+This covers most common use cases. For advanced scenarios -- such as
+typed element collections (`List<Item>`), date/time parsing, or
+annotation-driven property mapping (`@JsonProperty`, `@JsonFormat`) --
+use `jackson-databind` directly:
+
+[source,groovy]
+----
+@Grab('com.fasterxml.jackson.core:jackson-databind')
+import com.fasterxml.jackson.databind.ObjectMapper
+
+def config = new ObjectMapper().readValue(jsonString, ServerConfig)
+----
+
 === Builders
 
 Another way to create JSON from Groovy is to use `JsonBuilder` or 
`StreamingJsonBuilder`. Both builders provide a
diff --git a/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy 
b/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
index 02b686381e..abfa0c29c8 100644
--- a/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
+++ b/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
@@ -21,9 +21,12 @@ package json
 import groovy.json.JsonOutput
 import groovy.json.JsonParserType
 import groovy.json.JsonSlurper
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
 
-class JsonTest extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+class JsonTest {
 
     void testParseText() {
         // tag::parse_text[]
@@ -177,4 +180,64 @@ class JsonTest extends GroovyTestCase {
         // end::pretty_print[]
     }
 
+    // tag::typed_classes[]
+    static class ServerConfig {
+        String host
+        int port
+        boolean debug
+    }
+
+    static class AppConfig {
+        String name
+        ServerConfig server
+    }
+
+    enum Color { RED, GREEN, BLUE }
+
+    static class Item { String name; Color color }
+    // end::typed_classes[]
+
+    void testTypedCoercion() {
+        // tag::typed_coercion[]
+        def json = '{"host":"localhost","port":8080,"debug":true}'
+        def config = new JsonSlurper().parseText(json) as ServerConfig
+
+        assert config instanceof ServerConfig
+        assert config.host == 'localhost'
+        assert config.port == 8080
+        assert config.debug == true
+        // end::typed_coercion[]
+    }
+
+    void testTypedCoercionNested() {
+        // tag::typed_coercion_nested[]
+        def json = 
'{"name":"myapp","server":{"host":"localhost","port":9090,"debug":false}}'
+        def config = new JsonSlurper().parseText(json) as AppConfig
+
+        assert config.name == 'myapp'
+        assert config.server instanceof ServerConfig
+        assert config.server.host == 'localhost'
+        assert config.server.port == 9090
+        // end::typed_coercion_nested[]
+    }
+
+    void testTypedCoercionEnum() {
+        // tag::typed_coercion_enum[]
+        def item = new 
JsonSlurper().parseText('{"name":"widget","color":"GREEN"}') as Item
+        assert item.color == Color.GREEN
+        // end::typed_coercion_enum[]
+    }
+
+    void testJacksonDirectUsage() {
+        // tag::jackson_direct[]
+        // For advanced cases (typed collections, date parsing, @JsonProperty),
+        // use jackson-databind directly:
+        //
+        // @Grab('com.fasterxml.jackson.core:jackson-databind')
+        // import com.fasterxml.jackson.databind.ObjectMapper
+        //
+        // def config = new ObjectMapper().readValue(jsonString, ServerConfig)
+        // end::jackson_direct[]
+    }
+
 }

Reply via email to