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

lukaszlenart pushed a commit to branch docs/struts-7.3.0-content-audit
in repository https://gitbox.apache.org/repos/asf/struts-site.git

commit d23a4ad392f19d8e3e095e3a203c4d5582ea9bec
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Aug 3 07:34:14 2026 +0200

    docs: document JSON plugin changes in Struts 7.3.0
    
    WW-5652: Java records are serialized by iterating record components, @JSON 
and
    @JSONFieldBridge target record components, and Optional serializes as its
    contained value or null.
    
    WW-5641 / WW-5650: struts.json.writer / struts.json.reader overrides work
    again (they were ignored in 7.2.x), and the interceptor obtains a fresh
    reader/writer per request — custom implementations must be prototype-scoped.
    
    WW-5666: struts.json.maxLength is enforced while reading, in fixed-size
    chunks, and line terminators are no longer stripped (also in 6.11.0).
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 source/plugins/json/index.md | 54 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/source/plugins/json/index.md b/source/plugins/json/index.md
index 9be23a5ad..f8d159ddd 100644
--- a/source/plugins/json/index.md
+++ b/source/plugins/json/index.md
@@ -279,6 +279,42 @@ Enable this parameter through `struts.xml`:
 </result>
 ```
 
+### Java records and Optional
+
+> Since Struts 7.3.0
+
+Java records are serialized by iterating their record components, so a record 
no longer has to be wrapped in a bean to
+be returned as JSON:
+
+```java
+public record Person(String name, int age) {}
+```
+
+```json
+{"name": "Alice", "age": 30}
+```
+
+The `@JSON` and `@JSONFieldBridge` annotations now also target record 
components, so they can be declared on the
+component itself and are honoured on the generated accessor:
+
+```java
+public record Person(String name, @JSON(name = "years") int age) {}
+```
+
+The `excludeProperties` / `includeProperties` result parameters apply to 
record components as they do to bean
+properties.
+
+`java.util.Optional` values are serialized as the contained value, or as 
`null` when empty — an empty `Optional` is
+therefore subject to `excludeNullProperties` like any other null:
+
+```java
+public record Person(String name, Optional<String> nickname) {}
+```
+
+```json
+{"name": "Alice", "nickname": null}
+```
+
 ### Compressing the output
 
 Set the `enableGZIP` attribute to true to gzip the generated json response. 
The request **must** include `gzip` 
@@ -383,6 +419,18 @@ The implementation should then be defined in `struts.xml` 
like:
 </struts>
 ```
 
+The `struts.json.writer` and `struts.json.reader` overrides were ignored in 
Struts 7.2.x — the plugin's bean selection
+ran before the application's `struts.xml` was folded in, freezing the binding 
to the built-in implementations. This is
+fixed in Struts 7.3.0, see 
[WW-5641](https://issues.apache.org/jira/browse/WW-5641); if you carried a 
workaround for
+that regression, you can drop it.
+{:.alert .alert-warning}
+
+Declare the bean with `scope="prototype"`, as in the example above. Since 
Struts 7.3.0 the `json` interceptor obtains a
+fresh reader and writer per request, and the built-in implementations keep 
their parse/write state in plain instance
+fields — cross-request safety relies on the bean being prototype-scoped. A 
singleton-scoped custom implementation that
+holds per-request state will leak it between concurrent requests.
+{:.alert .alert-warning}
+
 There is an example at 
[struts-examples/json-customize/FlexJSONWriter.java](https://gitbox.apache.org/repos/asf?p=struts-examples.git;a=blob_plain;f=json-customize/src/main/java/org/demo/FlexJSONWriter.java;hb=HEAD).
 It replaces Struts default json serializer with 
[Flexjson](http://flexjson.sourceforge.net/) as below:
 
@@ -580,6 +628,12 @@ a `<param>` (following the same pattern as the fileUpload 
interceptor):
 <constant name="struts.json.maxLength" value="1048576"/>
 ```
 
+Since Struts 6.11.0 and 7.3.0 `struts.json.maxLength` is evaluated **while** 
the input is read, in fixed-size chunks,
+rather than after accumulating each line, so enforcement no longer depends on 
how the payload is split into lines. As
+part of the same change, line terminators are no longer stripped while 
reading: they are insignificant whitespace
+between tokens, but an unescaped control character inside a string value is 
now preserved rather than silently removed.
+{:.alert .alert-info}
+
 The reader and writer implementations are also pluggable via
 `struts.json.reader` and `struts.json.writer` (both default to `struts`).
 

Reply via email to