You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by ja...@apache.org on 2026/04/16 18:11:58 UTC

(grails-core) branch grails8-groovy5-sb4 updated: Restore grails.plugin.json.builder deprecation shims for Groovy 5 build

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

jamesfredley pushed a commit to branch grails8-groovy5-sb4
in repository https://gitbox.apache.org/repos/asf/grails-core.git


The following commit(s) were added to refs/heads/grails8-groovy5-sb4 by this push:
     new ff5d97284c Restore grails.plugin.json.builder deprecation shims for Groovy 5 build
ff5d97284c is described below

commit ff5d97284cf7daaa9d7900669bdaea18ab578bb2
Author: James Fredley <ja...@users.noreply.github.com>
AuthorDate: Thu Apr 16 14:11:52 2026 -0400

    Restore grails.plugin.json.builder deprecation shims for Groovy 5 build
    
    The `grails-views-gson:compileGroovy` task failed with
    `unable to resolve class grails.plugin.json.builder.StreamingJsonBuilder.StreamingJsonDelegate`
    at JsonViewWritableScript.groovy:77 and :88 (and other references in
    DefaultHalViewHelper.groovy).
    
    Root cause:
    
    - Commit 2110c45f36 ("refactor!: remove deprecated classes and methods")
      deleted the deprecated Grails-prefixed `grails.plugin.json.builder`
      classes (StreamingJsonBuilder, JsonGenerator, DefaultJsonGenerator),
      leaving only `JsonOutput.java`.
    - Commit 153e14c5ad ("fix: cherry-pick Groovy 5 fixes from Groovy 6
      canary branch") then rewrote JsonViewWritableScript.groovy and
      DefaultHalViewHelper.groovy to use the fully-qualified
      `grails.plugin.json.builder.StreamingJsonBuilder.StreamingJsonDelegate`
      type (and matching return types), matching what the canary branch
      uses. However, the actual class file was not cherry-picked along
      with the references, so the groovy compiler cannot resolve the type.
    
    The canary branch (origin/grails8-groovy6-canary) still carries the
    three deprecated shim classes. They are minimal (70-110 lines each) and
    simply extend the Groovy counterparts so that existing Grails code that
    references the old qualified names keeps compiling and behaving
    correctly against Groovy 5.
    
    Restore the three files verbatim from the canary branch:
    
    - grails.plugin.json.builder.StreamingJsonBuilder (extends
      `groovy.json.StreamingJsonBuilder`, overrides `call(Closure)` to use
      the Grails `StreamingJsonDelegate` that routes through
      `grails.plugin.json.builder.JsonOutput`'s OPEN_BRACE/CLOSE_BRACE
      constants, and exposes a nested `StreamingJsonDelegate` subclass
      with `cloneDelegateAndGetContent(...)` helper).
    - grails.plugin.json.builder.JsonGenerator (deprecated interface that
      extends `groovy.json.JsonGenerator` plus nested `Converter` /
      `Options` shims).
    - grails.plugin.json.builder.DefaultJsonGenerator (deprecated class
      that extends `groovy.json.DefaultJsonGenerator`).
    
    Local verification: `./gradlew build -x test -x groovydoc -x javadoc
    -x codenarcMain -x codenarcTest -x codenarcAst -x codenarcIntegrationTest
    -x checkstyleMain -x checkstyleTest -x checkstyleAst -PskipTests` now
    completes successfully (1254 actionable tasks). Only harmless
    self-deprecation warnings remain, which is expected for these
    forRemoval=true shims.
    
    Assisted-by: claude-code:claude-opus-4-7
---
 .../plugin/json/builder/DefaultJsonGenerator.java  |  37 +++++++
 .../grails/plugin/json/builder/JsonGenerator.java  |  74 ++++++++++++++
 .../plugin/json/builder/StreamingJsonBuilder.java  | 111 +++++++++++++++++++++
 3 files changed, 222 insertions(+)

diff --git a/grails-views-gson/src/main/groovy/grails/plugin/json/builder/DefaultJsonGenerator.java b/grails-views-gson/src/main/groovy/grails/plugin/json/builder/DefaultJsonGenerator.java
new file mode 100644
index 0000000000..c4cf21fae8
--- /dev/null
+++ b/grails-views-gson/src/main/groovy/grails/plugin/json/builder/DefaultJsonGenerator.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *    https://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 grails.plugin.json.builder;
+
+/**
+ * Temporary fork of DefaultJsonGenerator until Groovy 2.5.0 is out.
+ * <p>A JsonGenerator that can be configured with various {@link JsonGenerator.Options}.
+ * If the default options are sufficient consider using the static {@code JsonOutput.toJson}
+ * methods.
+ *
+ * @see JsonGenerator.Options#build()
+ * @since 2.5
+ * @deprecated Use {@link groovy.json.DefaultJsonGenerator} instead.
+ */
+@Deprecated(since = "7.1", forRemoval = true)
+public class DefaultJsonGenerator extends groovy.json.DefaultJsonGenerator {
+
+    protected DefaultJsonGenerator(groovy.json.DefaultJsonGenerator.Options options) {
+        super(options);
+    }
+}
diff --git a/grails-views-gson/src/main/groovy/grails/plugin/json/builder/JsonGenerator.java b/grails-views-gson/src/main/groovy/grails/plugin/json/builder/JsonGenerator.java
new file mode 100644
index 0000000000..bf39958328
--- /dev/null
+++ b/grails-views-gson/src/main/groovy/grails/plugin/json/builder/JsonGenerator.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *    https://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 grails.plugin.json.builder;
+
+/**
+ * Temporary fork of groovy JsonGenerator until Groovy 2.5.0 is out.
+ *
+ * <p>Generates JSON from objects.
+ *
+ * <p>The {@link Options} builder can be used to configure an instance of a JsonGenerator.
+ *
+ * @see Options#build()
+ * @since 2.5
+ * @deprecated Use {@link groovy.json.JsonGenerator} instead.
+ */
+@Deprecated(since = "7.1", forRemoval = true)
+public interface JsonGenerator extends groovy.json.JsonGenerator {
+
+    /**
+     * Handles converting a given type.
+     *
+     * @since 2.5
+     * @deprecated Use {@link groovy.json.JsonGenerator.Converter} instead.
+     */
+    @Deprecated(since = "7.1", forRemoval = true)
+    interface Converter extends groovy.json.JsonGenerator.Converter {
+
+    }
+
+    /**
+     * A builder used to construct a {@link JsonGenerator} instance that allows
+     * control over the serialized JSON output.  If you do not need to customize the
+     * output it is recommended to use the static {@code JsonOutput.toJson} methods.
+     *
+     * <p>
+     * Example:
+     * <pre><code class="groovyTestCase">
+     *     def generator = new groovy.json.JsonGenerator.Options()
+     *                         .excludeNulls()
+     *                         .dateFormat('yyyy')
+     *                         .excludeFieldsByName('bar', 'baz')
+     *                         .excludeFieldsByType(java.sql.Date)
+     *                         .build()
+     *
+     *     def input = [foo: null, lastUpdated: Date.parse('yyyy-MM-dd', '2014-10-24'),
+     *                   bar: 'foo', baz: 'foo', systemDate: new java.sql.Date(new Date().getTime())]
+     *
+     *     assert generator.toJson(input) == '{"lastUpdated":"2014"}'
+     * </code></pre>
+     *
+     * @since 2.5
+     * @deprecated Use {@link groovy.json.JsonGenerator.Options} instead.
+     */
+    @Deprecated(since = "7.1", forRemoval = true)
+    class Options extends groovy.json.JsonGenerator.Options {
+
+    }
+}
diff --git a/grails-views-gson/src/main/groovy/grails/plugin/json/builder/StreamingJsonBuilder.java b/grails-views-gson/src/main/groovy/grails/plugin/json/builder/StreamingJsonBuilder.java
new file mode 100644
index 0000000000..ea4cfe064a
--- /dev/null
+++ b/grails-views-gson/src/main/groovy/grails/plugin/json/builder/StreamingJsonBuilder.java
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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
+ *
+ *    https://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 grails.plugin.json.builder;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import groovy.lang.Closure;
+
+/**
+ * Temporary fork of {@link groovy.json.StreamingJsonBuilder} until Groovy 2.4.5 is out.
+ *
+ * @author Tim Yates
+ * @author Andrey Bloschetsov
+ * @author Graeme Rocher
+ *
+ * @since 1.8.1
+ * @deprecated Use {@link groovy.json.StreamingJsonBuilder} instead.
+ */
+@Deprecated(since = "7.1", forRemoval = true)
+public class StreamingJsonBuilder extends groovy.json.StreamingJsonBuilder {
+
+    private final Writer grailsWriter;
+    private final groovy.json.JsonGenerator grailsGenerator;
+
+    public StreamingJsonBuilder(Writer writer) {
+        super(writer);
+        this.grailsWriter = writer;
+        this.grailsGenerator = new groovy.json.JsonGenerator.Options().build();
+    }
+
+    @Deprecated(since = "7.1", forRemoval = true)
+    public StreamingJsonBuilder(Writer writer, grails.plugin.json.builder.JsonGenerator generator) {
+        super(writer, generator);
+        this.grailsWriter = writer;
+        this.grailsGenerator = generator;
+    }
+
+    public StreamingJsonBuilder(Writer writer, Object content) throws IOException {
+        super(writer, content);
+        this.grailsWriter = writer;
+        this.grailsGenerator = new groovy.json.JsonGenerator.Options().build();
+    }
+
+    public StreamingJsonBuilder(Writer writer, Object content, grails.plugin.json.builder.JsonGenerator generator) throws IOException {
+        super(writer, content, generator);
+        this.grailsWriter = writer;
+        this.grailsGenerator = generator;
+    }
+
+    public StreamingJsonBuilder(Writer writer, groovy.json.JsonGenerator generator) {
+        super(writer, generator);
+        this.grailsWriter = writer;
+        this.grailsGenerator = generator;
+    }
+
+    public StreamingJsonBuilder(Writer writer, Object content, groovy.json.JsonGenerator generator) throws IOException {
+        super(writer, content, generator);
+        this.grailsWriter = writer;
+        this.grailsGenerator = generator;
+    }
+
+    @Override
+    public Object call(@groovy.lang.DelegatesTo(value = StreamingJsonDelegate.class, strategy = Closure.DELEGATE_FIRST) Closure c) throws IOException {
+        grailsWriter.write(grails.plugin.json.builder.JsonOutput.OPEN_BRACE);
+        StreamingJsonDelegate.cloneDelegateAndGetContent(grailsWriter, c, true, grailsGenerator);
+        grailsWriter.write(grails.plugin.json.builder.JsonOutput.CLOSE_BRACE);
+        return null;
+    }
+
+    @Deprecated(since = "7.1", forRemoval = true)
+    public static class StreamingJsonDelegate extends groovy.json.StreamingJsonBuilder.StreamingJsonDelegate {
+
+        public StreamingJsonDelegate(Writer w, boolean first) {
+            super(w, first);
+        }
+
+        @Deprecated(since = "7.1", forRemoval = true)
+        public StreamingJsonDelegate(Writer w, boolean first, grails.plugin.json.builder.JsonGenerator generator) {
+            super(w, first, generator);
+        }
+
+        public StreamingJsonDelegate(Writer w, boolean first, groovy.json.JsonGenerator generator) {
+            super(w, first, generator);
+        }
+
+        public static void cloneDelegateAndGetContent(Writer w, Closure c, boolean first, groovy.json.JsonGenerator generator) {
+            StreamingJsonDelegate delegate = new StreamingJsonDelegate(w, first, generator);
+            Closure cloned = (Closure) c.clone();
+            cloned.setDelegate(delegate);
+            cloned.setResolveStrategy(Closure.DELEGATE_FIRST);
+            cloned.call();
+        }
+    }
+}