codeconsole commented on code in PR #16414:
URL: https://github.com/apache/grails-core/pull/16414#discussion_r4213514216


##########
grails-doc/src/en/guide/upgrading/upgrading90x.adoc:
##########
@@ -0,0 +1,189 @@
+////
+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.
+////
+
+=== Upgrade Instructions for Grails and Related Dependencies
+
+This guide outlines the changes to review when you upgrade a Grails project 
from Grails 8 to Grails 9.
+
+==== 1. `grails.converters.JSON` Writes JSON With Spring Boot's JsonMapper
+
+`render ... as JSON`, `respond` for a JSON request and every other use of 
`grails.converters.JSON` now write JSON through
+the application's Jackson `JsonMapper`, the one Spring Boot auto-configures. 
The mapper writes the JSON text (numbers and
+pretty printing), and writes every single value that it has a dedicated 
serializer for: dates and times, `Month`,
+`UUID`, `Locale`, `byte[]`, types with a `@JsonValue`, and the types of any 
Jackson module registered with the
+application. Those values render as Spring Boot renders them, and 
`spring.jackson.*` properties apply to them. For
+example, `spring.jackson.time-zone` writes `Date` and `Calendar` values in 
that time zone, and converts `OffsetDateTime`
+and `ZonedDateTime` values to it. When the application context has no 
`JsonMapper`, or has several and none is primary,
+as in a unit test, a default `JsonMapper` is used. To keep rendering JSON as 
Grails 8 did while you migrate, see
+<<renderingJsonAsGrails8,Rendering JSON As Grails 8 Did>>.
+
+Parsing JSON does not change. `JSON.parse`, `request.JSON` and `new 
JSONObject(String)` parse with Grails' own
+`JSONTokener`, as before: they accept the same syntax beyond strict JSON 
(single quotes, comments, unquoted values,
+uppercase literals, trailing commas, `new Date(...)`), return the same number 
types (`Integer`, `Long`, `BigInteger`,
+`Double` or `BigDecimal`, depending on the number) and the same `JSONObject` 
and `JSONArray` containers, which implement
+`Map` and `List`.
+
+Grails marshallers still render domain classes, beans, enums, collections, 
maps and arrays, and now records (as an
+object of their components) and `Optional` (as its value), so the values they 
contain are rendered as any other value
+is. A marshaller that an application registers, with 
`JSON.registerObjectMarshaller(...)` or an
+`ObjectMarshallerRegisterer`, still takes precedence over the mapper for the 
types it supports.

Review Comment:
   Agreed, the two PRs need one story before either merges. Here's what I 
propose. #16237 already matches most of it at its current head (c76fe76b8e).
   
   **Two layers, one switch each, and each switch means one thing:**
   
   1. **What `grails.converters.JSON` writes** (this PR). That covers `render 
... as JSON`, and `respond()` while `respond()` uses the converter.
      - In 9 it writes through Boot's `JsonMapper`, with Grails' marshallers on 
top.
      - `grails.converters.json.legacy: true` gives Grails 8's text, byte for 
byte, for both `render` and `respond`.
      - The switch isn't deprecated in 9, and we don't name a removal release 
until we know how many applications use it.
   2. **Which pipeline `respond()` uses** (#16237), set by 
`grails.web.rendering.json.spring`:
      - 9: the converter, by default.
      - 10: Spring's message converters, by default.
      - 11: the converter path for `respond()` is removed.
   
   So an application that wants exactly Grails 8's JSON in 9 sets 
`grails.converters.json.legacy: true` and nothing else. One that wants 
`respond()` to match a Spring Boot controller sets 
`grails.web.rendering.json.spring: true`. Neither switch changes what the other 
does.
   
   **`registerObjectMarshaller` is the migration tool, not the thing being 
migrated away from.** Both PRs keep it supported and undeprecated, for the 
converter:
   - Here, it's how to keep one type's Grails 8 format.
   - In #16237, it applies to `render ... as JSON` and to `respond()` while 
`respond()` uses the converter. Registering one no longer moves `respond()` to 
the converter: #16237 dropped that trigger, and only the setting decides.
   - The Spring path is customized with Jackson serializers.
   - #16237 deprecates the named-configuration APIs (`JSON.use`, 
`createNamedConfig`, …) for Grails 11, not `registerObjectMarshaller`.
   
   **Whichever PR merges second updates its wording to match the other.** If 
this one merges first, #16237 needs two changes:
   - Its "the legacy converter" becomes "the JSON converter".
   - Its §2 says that `respond()`'s default output in 9 is this PR's §1, with 
`grails.converters.json.legacy` for Grails 8's text.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to