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

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


The following commit(s) were added to refs/heads/main by this push:
     new f5761f8ee docs: JSON input parameter filtering & scalar-collection 
authorization (Struts 7.3.0) (#316)
f5761f8ee is described below

commit f5761f8ee49c3dc22e7b16022278e5bd0b8ae54f
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sat Jul 25 09:25:28 2026 +0200

    docs: JSON input parameter filtering & scalar-collection authorization 
(Struts 7.3.0) (#316)
    
    * docs: document JSON input parameter filtering (Struts 7.3.0)
    
    JSON population now applies the same name/value acceptability controls
    as the Parameters Interceptor (WW-4858, apache/struts#1773):
    
    - Always-on: framework-wide accepted/excluded name patterns, param-name
      max length (paramNameMaxLength, default 100), ParameterNameAware /
      ParameterValueAware callbacks, @StrutsParameter authorization.
    - Opt-in: acceptedValuePatterns / excludedValuePatterns and
      applyPropertyFiltersToInput (reuse excludeProperties/includeProperties
      on input).
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    * docs: clarify @StrutsParameter depth=1 on getters for primitive 
collections (JSON/REST)
    
    @StrutsParameter authorization on the JSON path exists since 7.2.0; PRs
    #1773/#1784 align its logic with ParametersInterceptor. Extend the
    collections example to make clear that populating a collection of simple
    types element by element (mySelection[0]) — as JSON/REST payloads do —
    requires @StrutsParameter(depth = 1) on the getter, not on the setter.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 4.8 <[email protected]>
---
 .../core-developers/struts-parameter-annotation.md | 21 +++++++++++
 source/plugins/json/index.md                       | 42 ++++++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/source/core-developers/struts-parameter-annotation.md 
b/source/core-developers/struts-parameter-annotation.md
index 1c2ac830e..33d5dfdc6 100644
--- a/source/core-developers/struts-parameter-annotation.md
+++ b/source/core-developers/struts-parameter-annotation.md
@@ -125,6 +125,27 @@ public class MyAction {
 }
 ```
 
+This covers the case where the whole collection is assigned at once (name
+`mySelection`, `depth = 0`), as a checkbox list submits it.
+
+When the collection is instead populated **element by element** through indexed
+names — `mySelection[0]`, `mySelection[1]` — the annotation must be on the
+**getter** with `depth = 1`, because each element path contains one bracket. 
This
+is how JSON and REST payloads bind a collection of simple types: a body such as
+`{"mySelection":["A","B"]}` populates `mySelection[0]` and `mySelection[1]`, so
+the getter must be annotated for the elements to be accepted.
+```java
+public class MyAction {
+    private List<String> mySelection;
+
+    @StrutsParameter(depth = 1)
+    public List<String> getMySelection() {
+        return mySelection;
+    }
+    // ... setter
+}
+```
+
 When populating properties of objects that are already in a collection, 
annotate the
 getter. Because reaching an element's property requires indexing into the 
collection
 *and then* following the property, this needs `depth = 2` (see
diff --git a/source/plugins/json/index.md b/source/plugins/json/index.md
index cfa7cff04..9be23a5ad 100644
--- a/source/plugins/json/index.md
+++ b/source/plugins/json/index.md
@@ -590,6 +590,48 @@ annotation **per property, during deserialization** — 
unauthorized fields are
 never set on the target object. Annotate the action properties that may be
 populated from the JSON request body.
 
+### Input parameter filtering
+
+Since Struts 7.3.0, populating an action from a JSON request body applies the
+same name/value acceptability controls that the
+[Parameters Interceptor](../../core-developers/parameters-interceptor.html)
+applies to ordinary HTTP request parameters. Filtering uses the same
+dotted/indexed key paths as form parameters (`address.city`, `items[0].name`),
+so the shared pattern checkers behave identically on JSON and form input.
+Population itself stays pure reflection over bean setters — no OGNL name
+evaluation is introduced on the JSON path.
+
+The following controls are **always on**:
+
+- **Excluded and accepted name patterns** — the same framework-wide
+  accepted/excluded parameter-name patterns the Parameters Interceptor uses. A
+  JSON key whose full dotted/indexed path matches an excluded pattern, or fails
+  to match any accepted pattern, is not populated.
+- **Maximum key-path length** — set with the `paramNameMaxLength` interceptor
+  param (default `100`). JSON keys whose full dotted path is longer are 
rejected.
+- **`ParameterNameAware` / `ParameterValueAware`** action callbacks — honored 
for
+  JSON input exactly as for form parameters.
+- **`@StrutsParameter` authorization** — see
+  [Parameter authorization](#parameter-authorization) above.
+
+The following controls are **opt-in** — disabled by default to preserve 
existing
+behavior for permissive JSON apps:
+
+| Interceptor param | Default | Effect |
+|-------------------|---------|--------|
+| `acceptedValuePatterns` | *(none)* | Comma-delimited regular expressions; 
when set, only JSON leaf **values** matching one of them are accepted (matching 
is case-insensitive). |
+| `excludedValuePatterns` | *(none)* | Comma-delimited regular expressions; 
JSON leaf **values** matching any of them are removed (matching is 
case-insensitive). |
+| `applyPropertyFiltersToInput` | `false` | When `true`, the interceptor's own 
`excludeProperties` / `includeProperties` patterns — otherwise used only for 
serialization output — also gate which JSON keys are populated on **input**. |
+
+```xml
+<interceptor-ref name="json">
+  <param name="paramNameMaxLength">120</param>
+  <param name="acceptedValuePatterns">[\w\s.@-]+</param>
+  <param name="applyPropertyFiltersToInput">true</param>
+  <param name="excludeProperties">login.password</param>
+</interceptor-ref>
+```
+
 ## JSON RPC
 
 The json plugin can be used to execute action methods from javascript and 
return the output. This feature was developed 

Reply via email to