[ 
https://issues.apache.org/jira/browse/WW-4034?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16276385#comment-16276385
 ] 

ASF GitHub Bot commented on WW-4034:
------------------------------------

lukaszlenart closed pull request #24: WW-4034 Example for customizing JSONWriter
URL: https://github.com/apache/struts-examples/pull/24
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/json-customize/pom.xml b/json-customize/pom.xml
new file mode 100644
index 0000000..9a441ff
--- /dev/null
+++ b/json-customize/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>struts-examples</artifactId>
+    <groupId>org.apache.struts</groupId>
+    <version>1.0.0</version>
+  </parent>
+
+  <groupId>org.demo</groupId>
+  <artifactId>json-customize</artifactId>
+  <version>1.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+  <name>Customized JSON produce</name>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.struts</groupId>
+      <artifactId>struts2-config-browser-plugin</artifactId>
+      <version>${struts2.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.struts</groupId>
+      <artifactId>struts2-json-plugin</artifactId>
+      <version>${struts2.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>net.sf.flexjson</groupId>
+      <artifactId>flexjson</artifactId>
+      <version>3.3</version>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.5</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+      <version>3.1.0</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>jsp-api</artifactId>
+      <version>2.0</version>
+      <scope>provided</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.3</version>
+        <configuration>
+          <encoding>UTF-8</encoding>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-maven-plugin</artifactId>
+        <version>${jetty-plugin.version}</version>
+        <configuration>
+          <webApp>
+            <contextPath>/${project.artifactId}</contextPath>
+          </webApp>
+          <stopKey>CTRL+C</stopKey>
+          <stopPort>8999</stopPort>
+          <scanIntervalSeconds>10</scanIntervalSeconds>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/json-customize/src/main/java/org/demo/Address.java 
b/json-customize/src/main/java/org/demo/Address.java
new file mode 100644
index 0000000..7000343
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/Address.java
@@ -0,0 +1,48 @@
+package org.demo;
+
+import java.util.List;
+
+public class Address {
+    private String name, street, city, state;
+    private List<Zipcode> zipcodes;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getStreet() {
+        return street;
+    }
+
+    public void setStreet(String street) {
+        this.street = street;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public List<Zipcode> getZipcodes() {
+        return zipcodes;
+    }
+
+    public void setZipcodes(List<Zipcode> zipcodes) {
+        this.zipcodes = zipcodes;
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/ExcludeTransformer.java 
b/json-customize/src/main/java/org/demo/ExcludeTransformer.java
new file mode 100644
index 0000000..e2a8fa1
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/ExcludeTransformer.java
@@ -0,0 +1,9 @@
+package org.demo;
+
+import flexjson.transformer.AbstractTransformer;
+
+public class ExcludeTransformer extends AbstractTransformer {
+    public void transform(Object o) {
+        return;
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/FlexJSONWriter.java 
b/json-customize/src/main/java/org/demo/FlexJSONWriter.java
new file mode 100644
index 0000000..7f24139
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/FlexJSONWriter.java
@@ -0,0 +1,79 @@
+/*
+ * 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.demo;
+
+import flexjson.JSONSerializer;
+import flexjson.transformer.DateTransformer;
+import org.apache.struts2.json.JSONException;
+import org.apache.struts2.json.JSONWriter;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.regex.Pattern;
+
+/**
+ * Customized JSONWriter using Flexjson
+ */
+public class FlexJSONWriter implements JSONWriter {
+    private String dateFormatter;
+
+    public String write(Object object) throws JSONException {
+        return this.write(object, null, null, false);
+    }
+
+    public String write(Object object, Collection<Pattern> excludeProperties, 
Collection<Pattern> includeProperties,
+                        boolean excludeNullProperties) throws JSONException {
+
+        JSONSerializer serializer = new JSONSerializer();
+        if (excludeProperties != null) {
+            for (Pattern p : excludeProperties) {
+                serializer = serializer.exclude(p.pattern());
+            }
+        }
+        if (includeProperties != null) {
+            for (Pattern p : includeProperties) {
+                serializer = serializer.include(p.pattern());
+            }
+        }
+        if (excludeNullProperties) {
+            serializer = serializer.transform(new ExcludeTransformer(), 
void.class);
+        }
+        if (dateFormatter != null) {
+            serializer = serializer.transform(new 
DateTransformer(dateFormatter), Date.class);
+        }
+        return serializer.serialize(object);
+    }
+
+    public void setIgnoreHierarchy(boolean ignoreHierarchy) {
+    }
+
+    public void setEnumAsBean(boolean enumAsBean) {
+    }
+
+    public void setDateFormatter(String dateFormatter) {
+        this.dateFormatter = dateFormatter;
+    }
+
+    public void setCacheBeanInfo(boolean cacheBeanInfo) {
+    }
+
+    public void setExcludeProxyProperties(boolean excludeProxyProperties) {
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/PasswordTransformer.java 
b/json-customize/src/main/java/org/demo/PasswordTransformer.java
new file mode 100644
index 0000000..b237f0c
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/PasswordTransformer.java
@@ -0,0 +1,9 @@
+package org.demo;
+
+import flexjson.transformer.AbstractTransformer;
+
+public class PasswordTransformer extends AbstractTransformer {
+    public void transform(Object o) {
+        getContext().writeQuoted("******");
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/Person.java 
b/json-customize/src/main/java/org/demo/Person.java
new file mode 100644
index 0000000..c66a7e3
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/Person.java
@@ -0,0 +1,52 @@
+package org.demo;
+
+import java.util.Date;
+import java.util.List;
+
+public class Person {
+    String name;
+    Date birthday;
+    String nickname;
+    List<Address> addresses;
+    List<Phone> phoneNumbers;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Date getBirthday() {
+        return birthday;
+    }
+
+    public void setBirthday(Date birthday) {
+        this.birthday = birthday;
+    }
+
+    public String getNickname() {
+        return nickname;
+    }
+
+    public void setNickname(String nickname) {
+        this.nickname = nickname;
+    }
+
+    public List<Address> getAddresses() {
+        return addresses;
+    }
+
+    public void setAddresses(List<Address> addresses) {
+        this.addresses = addresses;
+    }
+
+    public List<Phone> getPhoneNumbers() {
+        return phoneNumbers;
+    }
+
+    public void setPhoneNumbers(List<Phone> phoneNumbers) {
+        this.phoneNumbers = phoneNumbers;
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/Phone.java 
b/json-customize/src/main/java/org/demo/Phone.java
new file mode 100644
index 0000000..099f79d
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/Phone.java
@@ -0,0 +1,21 @@
+package org.demo;
+
+public class Phone {
+    private String name, number;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public void setNumber(String number) {
+        this.number = number;
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/ProduceAction.java 
b/json-customize/src/main/java/org/demo/ProduceAction.java
new file mode 100644
index 0000000..f6f43c8
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/ProduceAction.java
@@ -0,0 +1,83 @@
+/*
+ * 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.demo;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * <code>Set welcome message.</code>
+ */
+public class ProduceAction extends ActionSupport {
+
+    private User user;
+
+    public String execute() throws Exception {
+        user = new User();
+
+        user.setName("William Shakespeare");
+
+        SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
+        user.setBirthday(formatter.parse("26-Apr-1564"));
+
+        List<Phone> phoneNumbers = new ArrayList<Phone>();
+        Phone phone = new Phone();
+        phone.setName("cell");
+        phone.setNumber("555-123-4567");
+        phoneNumbers.add(phone);
+        phone = new Phone();
+        phone.setName("home");
+        phone.setNumber("555-987-6543");
+        phoneNumbers.add(phone);
+        phone = new Phone();
+        phone.setName("work");
+        phone.setNumber("555-678-3542");
+        phoneNumbers.add(phone);
+        user.setPhoneNumbers(phoneNumbers);
+
+        List<Address> addresses = new ArrayList<Address>();
+        Address address = new Address();
+        address.setName("home");
+        address.setCity("Stratford-upon-Avon");
+        address.setStreet("Henley");
+        List<Zipcode> zipcodes = new ArrayList<Zipcode>();
+        Zipcode zipcode = new Zipcode();
+        zipcode.setCode("CV37");
+        zipcodes.add(zipcode);
+        address.setZipcodes(zipcodes);
+        addresses.add(address);
+        user.setAddresses(addresses);
+
+        user.setLogin("WillShak");
+        user.setHashedPassword("9e107d9d372bb6826bd81d3542a419d6");
+        user.setLastLogin(new Date());
+        user.setPassword("will123shak456");
+
+        return SUCCESS;
+    }
+
+    public User getUser() {
+        return user;
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/User.java 
b/json-customize/src/main/java/org/demo/User.java
new file mode 100644
index 0000000..b72b8f5
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/User.java
@@ -0,0 +1,48 @@
+package org.demo;
+
+import flexjson.JSON;
+
+import java.util.Date;
+
+public class User extends Person {
+
+    private String login;
+    private String hashedPassword;
+    private Date lastLogin;
+    private String password;
+
+    @JSON(include = false)
+    public String getHashedPassword() {
+        return hashedPassword;
+    }
+
+    @JSON(name = "username")
+    public String getLogin() {
+        return login;
+    }
+
+    @JSON(transformer = PasswordTransformer.class)
+    public String getPassword() {
+        return password;
+    }
+
+    public void setLogin(String login) {
+        this.login = login;
+    }
+
+    public void setHashedPassword(String hashedPassword) {
+        this.hashedPassword = hashedPassword;
+    }
+
+    public Date getLastLogin() {
+        return lastLogin;
+    }
+
+    public void setLastLogin(Date lastLogin) {
+        this.lastLogin = lastLogin;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}
diff --git a/json-customize/src/main/java/org/demo/Zipcode.java 
b/json-customize/src/main/java/org/demo/Zipcode.java
new file mode 100644
index 0000000..e845078
--- /dev/null
+++ b/json-customize/src/main/java/org/demo/Zipcode.java
@@ -0,0 +1,13 @@
+package org.demo;
+
+public class Zipcode {
+    private String code;
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+}
diff --git a/json-customize/src/main/resources/log4j2.xml 
b/json-customize/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..e3c583b
--- /dev/null
+++ b/json-customize/src/main/resources/log4j2.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration>
+    <Appenders>
+        <Console name="STDOUT" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Logger name="com.opensymphony.xwork2" level="info"/>
+        <Logger name="org.apache.struts2" level="info"/>
+        <Logger name="org.demo" level="debug"/>
+        <Root level="warn">
+            <AppenderRef ref="STDOUT"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/json-customize/src/main/resources/struts.xml 
b/json-customize/src/main/resources/struts.xml
new file mode 100644
index 0000000..3fd22e1
--- /dev/null
+++ b/json-customize/src/main/resources/struts.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
+    "http://struts.apache.org/dtds/struts-2.5.dtd";>
+<struts>
+  <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
+  <constant name="struts.devMode" value="true"/>
+
+  <bean type="org.apache.struts2.json.JSONWriter" name="flexJSONWriter" 
class="org.demo.FlexJSONWriter"
+        scope="prototype"/>
+  <constant name="struts.json.writer" value="flexJSONWriter"/>
+  <constant name="struts.json.dateformat" value="MM/dd/yyyy"/>
+
+  <package name="default" namespace="/" extends="json-default">
+
+    <default-action-ref name="index"/>
+
+    <action name="index">
+      <result>/WEB-INF/index.jsp</result>
+    </action>
+
+    <action name="produce" class="org.demo.ProduceAction">
+      <result type="json">
+        <param name="includeProperties">addresses</param>
+        <param name="excludeProperties">addresses.state</param>
+        <param name="excludeNullProperties">true</param>
+        <param name="root">user</param>
+      </result>
+    </action>
+
+  </package>
+
+  <!-- Add addition packages and configuration here. -->
+</struts>
diff --git a/json-customize/src/main/webapp/WEB-INF/index.jsp 
b/json-customize/src/main/webapp/WEB-INF/index.jsp
new file mode 100644
index 0000000..df4afea
--- /dev/null
+++ b/json-customize/src/main/webapp/WEB-INF/index.jsp
@@ -0,0 +1,12 @@
+<%@ page contentType="text/html; charset=UTF-8" %>
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<html>
+<head>
+    <title>Customized JSON Result</title>
+</head>
+<body>
+
+<a href="produce.action">Produce Customized JSON</a>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/json-customize/src/main/webapp/WEB-INF/web.xml 
b/json-customize/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..8858656
--- /dev/null
+++ b/json-customize/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app id="struts_blank" version="2.4"
+         xmlns="http://java.sun.com/xml/ns/j2ee"; 
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd";>
+  <display-name>Struts Blank</display-name>
+
+  <filter>
+    <filter-name>struts2</filter-name>
+    <filter-class>
+      org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter
+    </filter-class>
+  </filter>
+
+  <filter-mapping>
+    <filter-name>struts2</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+</web-app>
diff --git a/pom.xml b/pom.xml
index 13b62bb..24d72d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,7 +40,7 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <struts2.version>2.5.13</struts2.version>
+        <struts2.version>2.5.14.1</struts2.version>
         <log4j2.version>2.8.2</log4j2.version>
         <jetty-plugin.version>9.4.7.v20170914</jetty-plugin.version>
     </properties>
@@ -66,6 +66,7 @@
         <module>http-session</module>
         <module>interceptors</module>
         <module>json</module>
+        <module>json-customize</module>
         <module>mailreader</module>
         <module>message-resource</module>
         <module>message-store</module>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


> Allow to use custom JSONwriter
> ------------------------------
>
>                 Key: WW-4034
>                 URL: https://issues.apache.org/jira/browse/WW-4034
>             Project: Struts 2
>          Issue Type: Improvement
>          Components: Plugin - JSON
>            Reporter: Emir Buğra KÖKSALAN
>            Priority: Minor
>              Labels: JSON
>             Fix For: 2.5.14
>
>
> Throws when accessing to a private inner class in that method:
> private void map(Map map, Method method) throws JSONException
> May be pass when trying to access a private class. example source code should 
> be:
> {code:java}
> private void map(Map map, Method method) throws JSONException {
>     this.add("{");
> ...
>     while (it.hasNext()) {
>         Map.Entry entry = (Map.Entry) it.next();
>         Object key = entry.getKey();
>         String expr = null;
>         if (this.buildExpr) {
>             try {
>                 if (key == null) {
>                     LOG.error("Cannot build expression for null key in " + 
> this.exprStack);
>                     continue;
>                 } else {
>                     expr = this.expandExpr(key.toString());
>                     if (this.shouldExcludeProperty(expr)) {
>                         continue;
>                     }
>                     expr = this.setExprStack(expr);
>                 }
>             }
>             catch (Exception ex) {
>                 LOG.error("Error: " + ex.getLocalizedMessage());
>                 continue;
>             }
>         }
>         if (hasData) {
>             this.add(',');
>         }
> ...
>     this.add("}");
> }
> {code}



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to