diff --git a/plugins/json/src/main/java/org/apache/struts2/json/JSONResult.java b/plugins/json/src/main/java/org/apache/struts2/json/JSONResult.java
index dfa0d6cff..c0ae8a6e6 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONResult.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONResult.java
@@ -20,12 +20,16 @@
*/
package org.apache.struts2.json;
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.ActionInvocation;
-import com.opensymphony.xwork2.Result;
-import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.util.ValueStack;
-import com.opensymphony.xwork2.util.WildcardUtil;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -33,13 +37,12 @@ import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.json.smd.SMDGenerator;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Result;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.WildcardUtil;
/**
*
This result serializes an action
@@ -84,6 +87,7 @@ public class JSONResult implements Result {
private boolean ignoreInterfaces = true;
private boolean enumAsBean = JSONWriter.ENUM_AS_BEAN_DEFAULT;
private boolean noCache = false;
+ private boolean cacheBeanInfo = true;
private boolean excludeNullProperties = false;
private String defaultDateFormat = null;
private int statusCode;
@@ -92,12 +96,18 @@ public class JSONResult implements Result {
private String contentType;
private String wrapPrefix;
private String wrapSuffix;
-
+ private boolean devMode = false;
+
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setDefaultEncoding(String val) {
this.defaultEncoding = val;
}
-
+
+ @Inject(StrutsConstants.STRUTS_DEVMODE)
+ public void setDevMode(String val) {
+ this.devMode = BooleanUtils.toBoolean(val);
+ }
+
/**
* Gets a list of regular expressions of properties to exclude from the JSON
* output.
@@ -171,7 +181,10 @@ public class JSONResult implements Result {
ActionContext actionContext = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
HttpServletResponse response = (HttpServletResponse) actionContext.get(StrutsStatics.HTTP_RESPONSE);
-
+
+ // only permit caching bean information when struts devMode = false
+ cacheBeanInfo = !devMode;
+
try {
Object rootObject;
rootObject = readRootObject(invocation);
@@ -202,7 +215,7 @@ public class JSONResult implements Result {
protected String createJSONString(HttpServletRequest request, Object rootObject) throws JSONException {
String json = JSONUtil.serialize(rootObject, excludeProperties, includeProperties, ignoreHierarchy,
- enumAsBean, excludeNullProperties, defaultDateFormat);
+ enumAsBean, excludeNullProperties, defaultDateFormat, cacheBeanInfo);
json = addCallbackIfApplicable(request, json);
return json;
}
diff --git a/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java b/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java
index 0ee024e3d..5c2e9fcc7 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java
@@ -20,20 +20,34 @@
*/
package org.apache.struts2.json;
-import com.opensymphony.xwork2.util.TextParseUtil;
-import com.opensymphony.xwork2.util.WildcardUtil;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.zip.GZIPOutputStream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.json.annotations.SMDMethod;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.lang.reflect.Method;
-import java.util.*;
-import java.util.regex.Pattern;
-import java.util.zip.GZIPOutputStream;
+import com.opensymphony.xwork2.util.TextParseUtil;
+import com.opensymphony.xwork2.util.WildcardUtil;
/**
* Wrapper for JSONWriter with some utility methods.
@@ -41,19 +55,23 @@ import java.util.zip.GZIPOutputStream;
public class JSONUtil {
public final static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
-
+ public static final boolean CACHE_BEAN_INFO_DEFAULT = true;
+
private static final Logger LOG = LogManager.getLogger(JSONUtil.class);
-
+
/**
* Serializes an object into JSON.
*
* @param object
* to be serialized
+ * @param cacheBeanInfo
+ * Specifies whether to cache bean info in the JSONWriter
* @return JSON string
* @throws JSONException
*/
- public static String serialize(Object object) throws JSONException {
+ public static String serialize(Object object, boolean cacheBeanInfo) throws JSONException {
JSONWriter writer = new JSONWriter();
+ writer.setCacheBeanInfo(cacheBeanInfo);
return writer.write(object);
}
@@ -74,8 +92,33 @@ public class JSONUtil {
public static String serialize(Object object, Collection excludeProperties,
Collection includeProperties, boolean ignoreHierarchy, boolean excludeNullProperties)
throws JSONException {
+ return serialize(object, excludeProperties, includeProperties,
+ ignoreHierarchy, excludeNullProperties, CACHE_BEAN_INFO_DEFAULT);
+ }
+
+ /**
+ * Serializes an object into JSON, excluding any properties matching any of
+ * the regular expressions in the given collection.
+ *
+ * @param object
+ * to be serialized
+ * @param excludeProperties
+ * Patterns matching properties to exclude
+ * @param ignoreHierarchy
+ * whether to ignore properties defined on base classes of the
+ * root object
+ * @param cacheBeanInfo
+ * Specifies whether to cache bean info in the JSONWriter
+ * @return JSON string
+ * @throws JSONException
+ */
+ public static String serialize(Object object, Collection excludeProperties,
+ Collection includeProperties, boolean ignoreHierarchy, boolean excludeNullProperties,
+ boolean cacheBeanInfo)
+ throws JSONException {
JSONWriter writer = new JSONWriter();
writer.setIgnoreHierarchy(ignoreHierarchy);
+ writer.setCacheBeanInfo(cacheBeanInfo);
return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
}
@@ -100,10 +143,38 @@ public class JSONUtil {
public static String serialize(Object object, Collection excludeProperties,
Collection includeProperties, boolean ignoreHierarchy, boolean enumAsBean,
boolean excludeNullProperties, String defaultDateFormat) throws JSONException {
+ return serialize(object, excludeProperties, includeProperties, ignoreHierarchy, enumAsBean,
+ excludeNullProperties, defaultDateFormat, CACHE_BEAN_INFO_DEFAULT);
+ }
+
+ /**
+ * Serializes an object into JSON, excluding any properties matching any of
+ * the regular expressions in the given collection.
+ *
+ * @param object
+ * to be serialized
+ * @param excludeProperties
+ * Patterns matching properties to exclude
+ * @param ignoreHierarchy
+ * whether to ignore properties defined on base classes of the
+ * root object
+ * @param enumAsBean
+ * whether to serialized enums a Bean or name=value pair
+ * @param defaultDateFormat
+ * date format used to serialize dates
+ * @param cacheBeanInfo
+ * Specifies whether to cache bean info in the JSONWriter
+ * @return JSON string
+ * @throws JSONException
+ */
+ public static String serialize(Object object, Collection excludeProperties,
+ Collection includeProperties, boolean ignoreHierarchy, boolean enumAsBean,
+ boolean excludeNullProperties, String defaultDateFormat, boolean cacheBeanInfo) throws JSONException {
JSONWriter writer = new JSONWriter();
writer.setIgnoreHierarchy(ignoreHierarchy);
writer.setEnumAsBean(enumAsBean);
writer.setDateFormatter(defaultDateFormat);
+ writer.setCacheBeanInfo(cacheBeanInfo);
return writer.write(object, excludeProperties, includeProperties, excludeNullProperties);
}
@@ -118,7 +189,23 @@ public class JSONUtil {
* @throws JSONException
*/
public static void serialize(Writer writer, Object object) throws IOException, JSONException {
- writer.write(serialize(object));
+ serialize(writer, object, CACHE_BEAN_INFO_DEFAULT);
+ }
+
+ /**
+ * Serializes an object into JSON to the given writer.
+ *
+ * @param writer
+ * Writer to serialize the object to
+ * @param object
+ * object to be serialized
+ * @param cacheBeanInfo
+ * Specifies whether to cache bean info in the JSONWriter
+ * @throws IOException
+ * @throws JSONException
+ */
+ public static void serialize(Writer writer, Object object, boolean cacheBeanInfo) throws IOException, JSONException {
+ writer.write(serialize(object, cacheBeanInfo));
}
/**
@@ -138,7 +225,29 @@ public class JSONUtil {
public static void serialize(Writer writer, Object object, Collection excludeProperties,
Collection includeProperties, boolean excludeNullProperties) throws IOException,
JSONException {
- writer.write(serialize(object, excludeProperties, includeProperties, true, excludeNullProperties));
+ serialize(writer, object, excludeProperties, includeProperties, excludeNullProperties, CACHE_BEAN_INFO_DEFAULT);
+ }
+
+ /**
+ * Serializes an object into JSON to the given writer, excluding any
+ * properties matching any of the regular expressions in the given
+ * collection.
+ *
+ * @param writer
+ * Writer to serialize the object to
+ * @param object
+ * object to be serialized
+ * @param excludeProperties
+ * Patterns matching properties to ignore
+ * @param cacheBeanInfo
+ * Specifies whether to cache bean info in the JSONWriter
+ * @throws IOException
+ * @throws JSONException
+ */
+ public static void serialize(Writer writer, Object object, Collection excludeProperties,
+ Collection includeProperties, boolean excludeNullProperties, boolean cacheBeanInfo)
+ throws IOException, JSONException {
+ writer.write(serialize(object, excludeProperties, includeProperties, true, excludeNullProperties, cacheBeanInfo));
}
/**
diff --git a/plugins/json/src/main/java/org/apache/struts2/json/JSONWriter.java b/plugins/json/src/main/java/org/apache/struts2/json/JSONWriter.java
index 154508401..c3b888911 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONWriter.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONWriter.java
@@ -74,6 +74,7 @@ public class JSONWriter {
private DateFormat formatter;
private boolean enumAsBean = ENUM_AS_BEAN_DEFAULT;
private boolean excludeNullProperties;
+ private boolean cacheBeanInfo = true;
/**
* @param object Object to be serialized into JSON
@@ -620,6 +621,10 @@ public class JSONWriter {
this.formatter = new SimpleDateFormat(defaultDateFormat);
}
}
+
+ public void setCacheBeanInfo(boolean cacheBeanInfo) {
+ this.cacheBeanInfo = cacheBeanInfo;
+ }
protected static class JSONAnnotationFinder {
private boolean serialize = true;
diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java
index bcd31e682..e9ca28353 100644
--- a/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java
+++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONResultTest.java
@@ -20,16 +20,6 @@
*/
package org.apache.struts2.json;
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.mock.MockActionInvocation;
-import com.opensymphony.xwork2.util.ValueStack;
-import org.apache.struts2.StrutsStatics;
-import org.apache.struts2.StrutsTestCase;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockHttpServletResponse;
-import org.springframework.mock.web.MockServletContext;
-
-import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
@@ -45,6 +35,18 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.StrutsStatics;
+import org.apache.struts2.StrutsTestCase;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockServletContext;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import com.opensymphony.xwork2.util.ValueStack;
+
/**
* JSONResultTest
*/
@@ -60,7 +62,7 @@ public class JSONResultTest extends StrutsTestCase {
Map map = new HashMap();
map.put("createtime", new Date());
try {
- JSONUtil.serialize(map);
+ JSONUtil.serialize(map, JSONUtil.CACHE_BEAN_INFO_DEFAULT);
} catch (JSONException e) {
fail(e.getMessage());
}
diff --git a/plugins/json/src/test/java/org/apache/struts2/json/JSONUtilTest.java b/plugins/json/src/test/java/org/apache/struts2/json/JSONUtilTest.java
index 2df5e47e6..dab592453 100644
--- a/plugins/json/src/test/java/org/apache/struts2/json/JSONUtilTest.java
+++ b/plugins/json/src/test/java/org/apache/struts2/json/JSONUtilTest.java
@@ -45,7 +45,7 @@ public class JSONUtilTest extends TestCase {
bean1.setEnumField(AnEnum.ValueA);
bean1.setEnumBean(AnEnumBean.Two);
- String json = JSONUtil.serialize(bean1);
+ String json = JSONUtil.serialize(bean1, JSONUtil.CACHE_BEAN_INFO_DEFAULT);
Map result = (Map) JSONUtil.deserialize(json);
assertEquals("str", result.get("stringField"));