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

lukaszlenart pushed a commit to branch WW-4858-json-parameter-filtering
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 064e59a99438e74d1bb21bf6d7dbee9926ddf345
Author: Lukasz Lenart <[email protected]>
AuthorDate: Wed Jul 8 20:39:47 2026 +0200

    WW-4858 feat(json): honor ParameterNameAware and ParameterValueAware on 
JSON population
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .../org/apache/struts2/json/JSONInterceptor.java   | 23 +++++++-
 .../apache/struts2/json/JSONInterceptorTest.java   | 32 +++++++++++
 .../struts2/json/ParameterAwareTestAction.java     | 63 ++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)

diff --git 
a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java 
b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
index c508fee86..37fb2fec5 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONInterceptor.java
@@ -19,6 +19,8 @@
 package org.apache.struts2.json;
 
 import org.apache.struts2.action.Action;
+import org.apache.struts2.action.ParameterNameAware;
+import org.apache.struts2.action.ParameterValueAware;
 import org.apache.struts2.ActionInvocation;
 import org.apache.struts2.inject.Inject;
 import org.apache.struts2.interceptor.AbstractInterceptor;
@@ -239,6 +241,8 @@ public class JSONInterceptor extends AbstractInterceptor {
                 filterUnacceptableKeysRecursive((Map) value, fullPath, target, 
action);
             } else if (value instanceof java.util.List) {
                 filterUnacceptableList((java.util.List) value, fullPath, 
target, action);
+            } else if (!isAcceptableValue(fullPath, value, action)) {
+                it.remove();
             }
         }
     }
@@ -248,11 +252,15 @@ public class JSONInterceptor extends AbstractInterceptor {
         // Use prefix+"[0]" so list element properties pick up one extra '[' 
in their path,
         // matching the indexed-path semantics of ParametersInterceptor (e.g. 
"items[0].key").
         String elementPrefix = prefix + "[0]";
-        for (Object item : list) {
+        Iterator it = list.iterator();
+        while (it.hasNext()) {
+            Object item = it.next();
             if (item instanceof Map) {
                 filterUnacceptableKeysRecursive((Map) item, elementPrefix, 
target, action);
             } else if (item instanceof java.util.List) {
                 filterUnacceptableList((java.util.List) item, elementPrefix, 
target, action);
+            } else if (!isAcceptableValue(elementPrefix, item, action)) {
+                it.remove();
             }
         }
     }
@@ -276,6 +284,19 @@ public class JSONInterceptor extends AbstractInterceptor {
                     fullPath, target.getClass().getName());
             return false;
         }
+        if (action instanceof ParameterNameAware nameAware && 
!nameAware.acceptableParameterName(fullPath)) {
+            LOG.debug("JSON body parameter [{}] rejected by ParameterNameAware 
action", fullPath);
+            return false;
+        }
+        return true;
+    }
+
+    private boolean isAcceptableValue(String fullPath, Object value, Object 
action) {
+        String stringValue = value == null ? null : String.valueOf(value);
+        if (action instanceof ParameterValueAware valueAware && 
!valueAware.acceptableParameterValue(stringValue)) {
+            LOG.debug("JSON body value for parameter [{}] rejected by 
ParameterValueAware action", fullPath);
+            return false;
+        }
         return true;
     }
 
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
index 82a562f00..6287ae892 100644
--- 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONInterceptorTest.java
@@ -765,6 +765,38 @@ public class JSONInterceptorTest extends StrutsTestCase {
         assertNull(action.getFoo());
     }
 
+    public void testParameterNameAwareRejectsKey() throws Exception {
+        this.request.setContent("{\"foo\":\"a\", \"bar\":\"b\"}".getBytes());
+        this.request.addHeader("Content-Type", "application/json");
+
+        JSONInterceptor interceptor = createInterceptor();
+        ParameterAwareTestAction action = new ParameterAwareTestAction();
+
+        this.invocation.setAction(action);
+        this.invocation.getStack().push(action);
+
+        interceptor.intercept(this.invocation);
+
+        assertEquals("a", action.getFoo());
+        assertNull(action.getBar());
+    }
+
+    public void testParameterValueAwareRejectsValue() throws Exception {
+        this.request.setContent("{\"foo\":\"blocked\", 
\"baz\":\"good\"}".getBytes());
+        this.request.addHeader("Content-Type", "application/json");
+
+        JSONInterceptor interceptor = createInterceptor();
+        ParameterAwareTestAction action = new ParameterAwareTestAction();
+
+        this.invocation.setAction(action);
+        this.invocation.getStack().push(action);
+
+        interceptor.intercept(this.invocation);
+
+        assertNull(action.getFoo());
+        assertEquals("good", action.getBaz());
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/ParameterAwareTestAction.java
 
b/plugins/json/src/test/java/org/apache/struts2/json/ParameterAwareTestAction.java
new file mode 100644
index 000000000..d71287cd9
--- /dev/null
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/ParameterAwareTestAction.java
@@ -0,0 +1,63 @@
+/*
+ * 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
+ *
+ *  http://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 org.apache.struts2.json;
+
+import org.apache.struts2.action.ParameterNameAware;
+import org.apache.struts2.action.ParameterValueAware;
+
+public class ParameterAwareTestAction implements ParameterNameAware, 
ParameterValueAware {
+
+    private String foo;
+    private String bar;
+    private String baz;
+
+    public String getFoo() {
+        return foo;
+    }
+
+    public void setFoo(String foo) {
+        this.foo = foo;
+    }
+
+    public String getBar() {
+        return bar;
+    }
+
+    public void setBar(String bar) {
+        this.bar = bar;
+    }
+
+    public String getBaz() {
+        return baz;
+    }
+
+    public void setBaz(String baz) {
+        this.baz = baz;
+    }
+
+    @Override
+    public boolean acceptableParameterName(String parameterName) {
+        return !"bar".equals(parameterName);
+    }
+
+    @Override
+    public boolean acceptableParameterValue(String parameterValue) {
+        return !"blocked".equals(parameterValue);
+    }
+}

Reply via email to