blob: 5f6aef7930017e907b8ca9b4284223ab441930cb [file] [log] [blame]
/*
* 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 java.math.BigDecimal;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
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.apache.struts2.util.TestUtils;
import org.springframework.aop.framework.ProxyFactory;
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
*/
public class JSONResultTest extends StrutsTestCase {
MockActionInvocation invocation;
MockHttpServletResponse response;
MockServletContext servletContext;
ActionContext context;
ValueStack stack;
MockHttpServletRequest request;
public void testJSONUtilNPEOnNullMehtod() {
Map map = new HashMap();
map.put("createtime", new Date());
try {
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
jsonUtil.serialize(map, JSONUtil.CACHE_BEAN_INFO_DEFAULT);
} catch (JSONException e) {
fail(e.getMessage());
}
}
public void testJSONWriterEndlessLoopOnExludedProperties() throws JSONException {
Pattern all = Pattern.compile(".*");
JSONWriter writer = new DefaultJSONWriter();
writer.write(Arrays.asList("a", "b"), Arrays.asList(all), null, false);
}
public void testSMDDisabledSMD() throws Exception {
JSONResult result = new JSONResult();
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
SMDActionTest1 action = new SMDActionTest1();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String smd = response.getContentAsString();
String normalizedActual = TestUtils.normalize(smd, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-8.txt"));
assertEquals(normalizedExpected, normalizedActual);
}
public void testSMDDefault() throws Exception {
JSONResult result = new JSONResult();
result.setEnableSMD(true);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
SMDActionTest1 action = new SMDActionTest1();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String smd = response.getContentAsString();
String normalizedActual = TestUtils.normalize(smd, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-1.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testSMDDefaultAnnotations() throws Exception {
JSONResult result = new JSONResult();
result.setEnableSMD(true);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
SMDActionTest2 action = new SMDActionTest2();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String smd = response.getContentAsString();
String normalizedActual = TestUtils.normalize(smd, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-2.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testExcludeNullPropeties() throws Exception {
JSONResult result = new JSONResult();
result.setExcludeNullProperties(true);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
action.setFoo("fool");
this.invocation.setAction(action);
result.execute(this.invocation);
String smd = response.getContentAsString();
String normalizedActual = TestUtils.normalize(smd, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("nulls-1.txt"));
assertEquals(normalizedExpected, normalizedActual);
}
public void testNotTraverseOrIncludeProxyInfo() throws Exception {
JSONResult result = new JSONResult();
JSONUtil jsonUtil = new JSONUtil();
JSONWriter writer = new DefaultJSONWriter();
jsonUtil.setWriter(writer);
result.setJsonUtil(jsonUtil);
Object proxiedAction = new ProxyFactory(new TestAction2()).getProxy();
stack.push(proxiedAction);
this.invocation.setAction(proxiedAction);
try {
result.execute(this.invocation);
} catch (Exception ignored) {
}
String out = response.getContentAsString();
String normalizedActual = TestUtils.normalize(out, true);
String normalizedExpected = "{\"name\":\"name\"}";
assertNotSame(normalizedExpected, normalizedActual);
response.setCommitted(false);
response.reset();
writer.setExcludeProxyProperties(true);
result.execute(this.invocation);
out = response.getContentAsString();
normalizedActual = TestUtils.normalize(out, true);
assertEquals(normalizedExpected, normalizedActual);
}
public void testWrapPrefix() throws Exception {
JSONResult result = new JSONResult();
result.setWrapPrefix("_prefix_");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction2 action = new TestAction2();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String out = response.getContentAsString();
String normalizedActual = TestUtils.normalize(out, true);
String normalizedExpected = "_prefix_{\"name\":\"name\"}";
assertEquals(normalizedExpected, normalizedActual);
}
public void testSuffix() throws Exception {
JSONResult result = new JSONResult();
result.setWrapSuffix("_suffix_");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction2 action = new TestAction2();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String out = response.getContentAsString();
String normalizedActual = TestUtils.normalize(out, true);
String normalizedExpected = "{\"name\":\"name\"}_suffix_";
assertEquals(normalizedExpected, normalizedActual);
}
public void testCustomDateFormat() throws Exception {
JSONResult result = new JSONResult();
result.setDefaultDateFormat("MM-dd-yyyy");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
SingleDateBean dateBean = new SingleDateBean();
dateBean.setDate(sdf.parse("2012-12-23 10:10:10 GMT"));
stack.push(dateBean);
this.invocation.setAction(dateBean);
result.execute(this.invocation);
String out = response.getContentAsString();
assertEquals("{\"date\":\"12-23-2012\"}", out);
}
public void testPrefixAndSuffix() throws Exception {
JSONResult result = new JSONResult();
result.setWrapPrefix("_prefix_");
result.setWrapSuffix("_suffix_");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction2 action = new TestAction2();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String out = response.getContentAsString();
String normalizedActual = TestUtils.normalize(out, true);
String normalizedExpected = "_prefix_{\"name\":\"name\"}_suffix_";
assertEquals(normalizedExpected, normalizedActual);
}
public void testPrefix() throws Exception {
JSONResult result = new JSONResult();
result.setExcludeNullProperties(true);
result.setPrefix(true);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
action.setFoo("fool");
this.invocation.setAction(action);
result.execute(this.invocation);
String smd = response.getContentAsString();
String normalizedActual = TestUtils.normalize(smd, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("prefix-1.txt"));
assertEquals(normalizedExpected, normalizedActual);
}
@SuppressWarnings("unchecked")
public void test() throws Exception {
JSONResult result = new JSONResult();
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
// test scape characters
action.setArray(new String[] { "a", "a", "\"", "\\", "/", "\b", "\f", "\n", "\r", "\t" });
List list = new ArrayList();
list.add("b");
list.add(1);
list.add(new int[] { 10, 12 });
action.setCollection(list);
// beans
List collection2 = new ArrayList();
Bean bean1 = new Bean();
bean1.setBigDecimal(new BigDecimal("111111.111111"));
bean1.setBigInteger(new BigInteger("111111111111"));
bean1.setStringField("str");
bean1.setBooleanField(true);
bean1.setCharField('s');
bean1.setDoubleField(10.1);
bean1.setFloatField(1.5f);
bean1.setIntField(10);
bean1.setLongField(100);
bean1.setEnumField(AnEnum.ValueA);
bean1.setEnumBean(AnEnumBean.One);
Bean bean2 = new Bean();
bean2.setStringField(" ");
bean2.setBooleanField(false);
bean2.setFloatField(1.1f);
bean2.setDoubleField(2.2);
bean2.setEnumField(AnEnum.ValueB);
bean2.setEnumBean(AnEnumBean.Two);
// circular reference
bean1.setObjectField(bean2);
bean2.setObjectField(bean1);
collection2.add(bean1);
action.setCollection2(collection2);
// keep order in map
Map map = new LinkedHashMap();
map.put("a", 1);
map.put("c", new float[] { 1.0f, 2.0f });
action.setMap(map);
action.setFoo("foo");
// should be ignored, marked 'transient'
action.setBar("bar");
// date
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 1999);
calendar.set(Calendar.MONTH, Calendar.DECEMBER);
calendar.set(Calendar.DAY_OF_MONTH, 31);
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
action.setDate(calendar.getTime());
action.setDate2(calendar.getTime());
this.invocation.setAction(action);
result.execute(this.invocation);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
@SuppressWarnings("unchecked")
public void testHierarchy() throws Exception {
JSONResult result = new JSONResult();
result.setIgnoreHierarchy(false);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction3 action = new TestAction3();
stack.push(action);
this.invocation.setAction(action);
result.execute(this.invocation);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-4.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
@SuppressWarnings("unchecked")
public void testCommentWrap() throws Exception {
JSONResult result = new JSONResult();
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
// test scape characters
action.setArray(new String[] { "a", "a", "\"", "\\", "/", "\b", "\f", "\n", "\r", "\t" });
List list = new ArrayList();
list.add("b");
list.add(1);
list.add(new int[] { 10, 12 });
action.setCollection(list);
// beans
List collection2 = new ArrayList();
Bean bean1 = new Bean();
bean1.setStringField("str");
bean1.setBooleanField(true);
bean1.setCharField('s');
bean1.setDoubleField(10.1);
bean1.setFloatField(1.5f);
bean1.setIntField(10);
bean1.setLongField(100);
bean1.setEnumField(null);
bean1.setEnumBean(null);
Bean bean2 = new Bean();
bean2.setStringField(" ");
bean2.setBooleanField(false);
bean2.setFloatField(1.1f);
bean2.setDoubleField(2.2);
bean2.setEnumField(AnEnum.ValueC);
bean2.setEnumBean(AnEnumBean.Three);
// circular reference
bean1.setObjectField(bean2);
bean2.setObjectField(bean1);
collection2.add(bean1);
action.setCollection2(collection2);
// keep order in map
Map map = new LinkedHashMap();
map.put("a", 1);
map.put("c", new float[] { 1.0f, 2.0f });
action.setMap(map);
action.setFoo("foo");
// should be ignored, marked 'transient'
action.setBar("bar");
// date
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 1999);
calendar.set(Calendar.MONTH, Calendar.DECEMBER);
calendar.set(Calendar.DAY_OF_MONTH, 31);
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
action.setDate(calendar.getTime());
action.setDate2(calendar.getTime());
this.invocation.setAction(action);
result.setWrapWithComments(true);
result.execute(this.invocation);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-3.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
private void executeTest2Action(JSONResult result) throws Exception {
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
// beans
Bean bean1 = new Bean();
bean1.setStringField("str");
bean1.setBooleanField(true);
bean1.setCharField('s');
bean1.setDoubleField(10.1);
bean1.setFloatField(1.5f);
bean1.setIntField(10);
bean1.setLongField(100);
bean1.setEnumField(AnEnum.ValueA);
bean1.setEnumBean(AnEnumBean.One);
// set root
action.setBean(bean1);
result.setRoot("bean");
stack.push(action);
this.invocation.setStack(stack);
this.invocation.setAction(action);
result.execute(this.invocation);
}
public void test2() throws Exception {
JSONResult result = new JSONResult();
executeTest2Action(result);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-2.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testJSONP() throws Exception {
JSONResult result = new JSONResult();
result.setCallbackParameter("callback");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
request.addParameter("callback", "exec");
executeTest2Action(result);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("jsonp-1.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testNoCache() throws Exception {
JSONResult result = new JSONResult();
result.setNoCache(true);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
executeTest2Action(result);
assertEquals("no-cache", response.getHeader("Cache-Control"));
assertEquals("0", response.getHeader("Expires"));
assertEquals("No-cache", response.getHeader("Pragma"));
}
public void testContentType() throws Exception {
JSONResult result = new JSONResult();
result.setContentType("some_super_content");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
executeTest2Action(result);
assertEquals("some_super_content;charset=UTF-8", response.getContentType());
}
public void testStatusCode() throws Exception {
JSONResult result = new JSONResult();
result.setStatusCode(HttpServletResponse.SC_CONTINUE);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
executeTest2Action(result);
assertEquals(HttpServletResponse.SC_CONTINUE, response.getStatus());
}
/**
* Repeats test2 but with the Enum serialized as a bean
*/
public void test2WithEnumBean() throws Exception {
JSONResult result = new JSONResult();
result.setEnumAsBean(true);
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
executeTest2Action(result);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-2-enum.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
/**
* Ensures that properties of given root object are read as shallow
* (non-recursive) unless specifically included.
*/
public void testIncludeProperties() throws Exception {
JSONResult result = new JSONResult();
result.setIncludeProperties("foo");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
action.setFoo("fooValue");
action.setBean(new Bean());
this.invocation.setAction(action);
result.execute(this.invocation);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-9.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testIncludePropertiesWithList() throws Exception {
JSONResult result = new JSONResult();
result.setIncludeProperties("^list\\[\\d+\\]\\.booleanField");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
List list = new ArrayList();
list.add(new Bean());
list.add(new Bean());
list.add(new Bean());
action.setList(list);
this.invocation.setAction(action);
result.execute(this.invocation);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-10.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testIncludePropertiesWithSetList() throws Exception {
JSONResult result = new JSONResult();
result.setIncludeProperties("^set\\[\\d+\\]\\.list\\[\\d+\\]\\.booleanField");
JSONUtil jsonUtil = new JSONUtil();
jsonUtil.setWriter(new DefaultJSONWriter());
result.setJsonUtil(jsonUtil);
TestAction action = new TestAction();
stack.push(action);
Set set = new LinkedHashSet();
TestAction a1 = new TestAction();
List list = new ArrayList();
list.add(new Bean());
list.add(new Bean());
list.add(new Bean());
a1.setList(list);
set.add(a1);
TestAction a2 = new TestAction();
list = new ArrayList();
list.add(new Bean());
list.add(new Bean());
a2.setList(list);
set.add(a2);
action.setSet(set);
this.invocation.setAction(action);
result.execute(this.invocation);
String json = response.getContentAsString();
String normalizedActual = TestUtils.normalize(json, true);
String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-11.txt"));
assertEquals(normalizedExpected, normalizedActual);
assertEquals("application/json;charset=UTF-8", response.getContentType());
}
public void testDefaultEncoding() throws Exception {
// given
JSONResult json = new JSONResult();
json.setDefaultEncoding("UTF-16");
// when
String encoding = json.getEncoding();
// thn
assertEquals("UTF-16", encoding);
}
public void testEncoding() throws Exception {
// given
JSONResult json = new JSONResult();
json.setEncoding("UTF-8");
json.setDefaultEncoding("UTF-8");
// when
String encoding = json.getEncoding();
// thn
assertEquals("UTF-8", encoding);
}
@Override
protected void setUp() throws Exception {
super.setUp();
this.response = new MockHttpServletResponse();
this.request = new MockHttpServletRequest();
this.request.setRequestURI("http://sumeruri");
this.context = ActionContext.getContext();
this.context.put(StrutsStatics.HTTP_RESPONSE, this.response);
this.context.put(StrutsStatics.HTTP_REQUEST, this.request);
this.stack = context.getValueStack();
this.servletContext = new MockServletContext();
this.context.put(StrutsStatics.SERVLET_CONTEXT, this.servletContext);
this.invocation = new MockActionInvocation();
this.invocation.setInvocationContext(this.context);
this.invocation.setStack(this.stack);
}
}