使用struts2的json插件时,自己定义日期格式经常使用的方式是在get属性上加入@JSON注解,这个对于少量Date属性还能够,可是假设date字段多了,总不可能去给每一个date get方法加入json注解吧!

发现极大不便后查看了sturts-plugin.xml 中的json-default定义,源代码跟踪到json拦截器内部一点发现都没有,自己定义

org.apache.struts2.json.JSONPopulator中的dateFormatter属性全然不起效果。可是在同一个包下:org.apache.struts2.json 发现了类:JSONWriter 在这里才找到了一些端倪

将源代码中的

    /**
* Add date to buffer
*/
protected void date(Date date, Method method) {
JSON json = null;
if (method != null)
json = method.getAnnotation(JSON.class);
if (this.formatter == null)
this.formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat formatter = (json != null) && (json.format().length() > 0) ? new SimpleDateFormat(json
.format()) : this.formatter;
this.string(formatter.format(date));
}
SimpleDateFormat 格式改成自己定义日期格式就可以,这样全局json 日期格式就自己定义完毕了!
注意:覆盖时仅仅须要自己定义包:org.apache.struts2.json将改动后的<span style="font-family: Arial, Helvetica, sans-serif;">JSONWriter放到包下就可以,没有必要去改动插件中的源代码信息 </span>

以下附上整个类的源代码:

/*
* $Id$
*
* 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 com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.json.annotations.JSON;
import org.apache.struts2.json.annotations.JSONFieldBridge;
import org.apache.struts2.json.annotations.JSONParameter;
import org.apache.struts2.json.bridge.FieldBridge;
import org.apache.struts2.json.bridge.ParameterizedBridge; import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.text.CharacterIterator;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.StringCharacterIterator;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern; /**
* <p>
* Serializes an object into JavaScript Object Notation (JSON). If cyclic
* references are detected they will be nulled out.
* </p>
*/
public class JSONWriter { private static final Logger LOG = LoggerFactory.getLogger(JSONWriter.class); /**
* By default, enums are serialised as name=value pairs
*/
public static final boolean ENUM_AS_BEAN_DEFAULT = false; private static char[] hex = "0123456789ABCDEF".toCharArray(); private static final ConcurrentMap<Class<?>, BeanInfo> BEAN_INFO_CACHE_IGNORE_HIERARCHY = new ConcurrentHashMap<Class<?>, BeanInfo>();
private static final ConcurrentMap<Class<?>, BeanInfo> BEAN_INFO_CACHE = new ConcurrentHashMap<Class<?>, BeanInfo>(); private StringBuilder buf = new StringBuilder();
private Stack<Object> stack = new Stack<Object>();
private boolean ignoreHierarchy = true;
private Object root;
private boolean buildExpr = true;
private String exprStack = "";
private Collection<Pattern> excludeProperties;
private Collection<Pattern> includeProperties;
private DateFormat formatter;
private boolean enumAsBean = ENUM_AS_BEAN_DEFAULT;
private boolean excludeNullProperties; /**
* @param object Object to be serialized into JSON
* @return JSON string for object
* @throws JSONException
*/
public String write(Object object) throws JSONException {
return this.write(object, null, null, false);
} /**
* @param object Object to be serialized into JSON
* @return JSON string for object
* @throws JSONException
*/
public String write(Object object, Collection<Pattern> excludeProperties,
Collection<Pattern> includeProperties, boolean excludeNullProperties) throws JSONException {
this.excludeNullProperties = excludeNullProperties;
this.buf.setLength(0);
this.root = object;
this.exprStack = "";
this.buildExpr = ((excludeProperties != null) && !excludeProperties.isEmpty())
|| ((includeProperties != null) && !includeProperties.isEmpty());
this.excludeProperties = excludeProperties;
this.includeProperties = includeProperties;
this.value(object, null); return this.buf.toString();
} /**
* Detect cyclic references
*/
protected void value(Object object, Method method) throws JSONException {
if (object == null) {
this.add("null"); return;
} if (this.stack.contains(object)) {
Class clazz = object.getClass(); // cyclic reference
if (clazz.isPrimitive() || clazz.equals(String.class)) {
this.process(object, method);
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("Cyclic reference detected on " + object);
} this.add("null");
} return;
} this.process(object, method);
} /**
* Serialize object into json
*/
protected void process(Object object, Method method) throws JSONException {
this.stack.push(object); if (object instanceof Class) {
this.string(object);
} else if (object instanceof Boolean) {
this.bool((Boolean) object);
} else if (object instanceof Number) {
this.add(object);
} else if (object instanceof String) {
this.string(object);
} else if (object instanceof Character) {
this.string(object);
} else if (object instanceof Map) {
this.map((Map) object, method);
} else if (object.getClass().isArray()) {
this.array(object, method);
} else if (object instanceof Iterable) {
this.array(((Iterable) object).iterator(), method);
} else if (object instanceof Date) {
this.date((Date) object, method);
} else if (object instanceof Calendar) {
this.date(((Calendar) object).getTime(), method);
} else if (object instanceof Locale) {
this.string(object);
} else if (object instanceof Enum) {
this.enumeration((Enum) object);
} else {
processCustom(object, method);
} this.stack.pop();
} /**
* Serialize custom object into json
*/
protected void processCustom(Object object, Method method) throws JSONException {
this.bean(object);
} /**
* Instrospect bean and serialize its properties
*/
protected void bean(Object object) throws JSONException {
this.add("{"); BeanInfo info; try {
Class clazz = object.getClass(); info = ((object == this.root) && this.ignoreHierarchy)
? getBeanInfoIgnoreHierarchy(clazz)
: getBeanInfo(clazz); PropertyDescriptor[] props = info.getPropertyDescriptors(); boolean hasData = false;
for (PropertyDescriptor prop : props) {
String name = prop.getName();
Method accessor = prop.getReadMethod();
Method baseAccessor = findBaseAccessor(clazz, accessor); if (baseAccessor != null) {
if (baseAccessor.isAnnotationPresent(JSON.class)) {
JSONAnnotationFinder jsonFinder = new JSONAnnotationFinder(baseAccessor).invoke(); if (!jsonFinder.shouldSerialize()) continue;
if (jsonFinder.getName() != null) {
name = jsonFinder.getName();
}
}
// ignore "class" and others
if (this.shouldExcludeProperty(prop)) {
continue;
}
String expr = null;
if (this.buildExpr) {
expr = this.expandExpr(name);
if (this.shouldExcludeProperty(expr)) {
continue;
}
expr = this.setExprStack(expr);
} Object value = accessor.invoke(object);
if (baseAccessor.isAnnotationPresent(JSONFieldBridge.class)) {
value = getBridgedValue(baseAccessor, value);
} boolean propertyPrinted = this.add(name, value, accessor, hasData);
hasData = hasData || propertyPrinted;
if (this.buildExpr) {
this.setExprStack(expr);
}
}
} // special-case handling for an Enumeration - include the name() as
// a property */
if (object instanceof Enum) {
Object value = ((Enum) object).name();
this.add("_name", value, object.getClass().getMethod("name"), hasData);
}
} catch (Exception e) {
throw new JSONException(e);
} this.add("}");
} protected BeanInfo getBeanInfoIgnoreHierarchy(final Class<?> clazz) throws IntrospectionException {
BeanInfo beanInfo = BEAN_INFO_CACHE_IGNORE_HIERARCHY.get(clazz);
if (beanInfo != null) {
return beanInfo;
}
beanInfo = Introspector.getBeanInfo(clazz, clazz.getSuperclass());
BEAN_INFO_CACHE_IGNORE_HIERARCHY.put(clazz, beanInfo);
return beanInfo;
} protected BeanInfo getBeanInfo(final Class<?> clazz) throws IntrospectionException {
BeanInfo beanInfo = BEAN_INFO_CACHE.get(clazz);
if (beanInfo != null) {
return beanInfo;
}
beanInfo = Introspector.getBeanInfo(clazz);
BEAN_INFO_CACHE.put(clazz, beanInfo);
return beanInfo;
} protected Object getBridgedValue(Method baseAccessor, Object value) throws InstantiationException, IllegalAccessException {
JSONFieldBridge fieldBridgeAnn = baseAccessor.getAnnotation(JSONFieldBridge.class);
if (fieldBridgeAnn != null) {
Class impl = fieldBridgeAnn.impl();
FieldBridge instance = (FieldBridge) impl.newInstance(); if (fieldBridgeAnn.params().length > 0 && ParameterizedBridge.class.isAssignableFrom(impl)) {
Map<String, String> params = new HashMap<String, String>(fieldBridgeAnn.params().length);
for (JSONParameter param : fieldBridgeAnn.params()) {
params.put(param.name(), param.value());
}
((ParameterizedBridge) instance).setParameterValues(params);
}
value = instance.objectToString(value);
}
return value;
} protected Method findBaseAccessor(Class clazz, Method accessor) {
Method baseAccessor = null;
if (clazz.getName().contains("$$EnhancerByCGLIB$$")) {
try {
baseAccessor = Thread.currentThread().getContextClassLoader().loadClass(
clazz.getName().substring(0, clazz.getName().indexOf("$$"))).getMethod(
accessor.getName(), accessor.getParameterTypes());
} catch (Exception ex) {
LOG.debug(ex.getMessage(), ex);
}
} else if (clazz.getName().contains("$$_javassist")) {
try {
baseAccessor = Class.forName(
clazz.getName().substring(0, clazz.getName().indexOf("_$$")))
.getMethod(accessor.getName(), accessor.getParameterTypes());
} catch (Exception ex) {
LOG.debug(ex.getMessage(), ex);
}
} else {
return accessor;
}
return baseAccessor;
} /**
* Instrospect an Enum and serialize it as a name/value pair or as a bean
* including all its own properties
*/
protected void enumeration(Enum enumeration) throws JSONException {
if (enumAsBean) {
this.bean(enumeration);
} else {
this.string(enumeration.name());
}
} protected boolean shouldExcludeProperty(PropertyDescriptor prop) throws SecurityException, NoSuchFieldException {
String name = prop.getName();
return name.equals("class")
|| name.equals("declaringClass")
|| name.equals("cachedSuperClass")
|| name.equals("metaClass");
} protected String expandExpr(int i) {
return this.exprStack + "[" + i + "]";
} protected String expandExpr(String property) {
if (this.exprStack.length() == 0) {
return property;
}
return this.exprStack + "." + property;
} protected String setExprStack(String expr) {
String s = this.exprStack;
this.exprStack = expr;
return s;
} protected boolean shouldExcludeProperty(String expr) {
if (this.excludeProperties != null) {
for (Pattern pattern : this.excludeProperties) {
if (pattern.matcher(expr).matches()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Ignoring property because of exclude rule: " + expr);
}
return true;
}
}
} if (this.includeProperties != null) {
for (Pattern pattern : this.includeProperties) {
if (pattern.matcher(expr).matches()) {
return false;
}
}
if (LOG.isDebugEnabled()){
LOG.debug("Ignoring property because of include rule: " + expr);
}
return true;
}
return false;
} /**
* Add name/value pair to buffer
*/
protected boolean add(String name, Object value, Method method, boolean hasData) throws JSONException {
if (excludeNullProperties && value == null) {
return false;
}
if (hasData) {
this.add(',');
}
this.add('"');
this.add(name);
this.add("\":");
this.value(value, method);
return true;
} /**
* Add map to buffer
*/
protected void map(Map map, Method method) throws JSONException {
this.add("{"); Iterator it = map.entrySet().iterator(); boolean warnedNonString = false; // one report per map
boolean hasData = false;
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
if (excludeNullProperties && entry.getValue() == null) {
continue;
} Object key = entry.getKey();
if (key == null) {
LOG.error("Cannot build expression for null key in #0", exprStack);
continue;
} String expr = null;
if (this.buildExpr) {
expr = this.expandExpr(key.toString());
if (this.shouldExcludeProperty(expr)) {
continue;
}
expr = this.setExprStack(expr);
}
if (hasData) {
this.add(',');
}
hasData = true;
if (!warnedNonString && !(key instanceof String)) {
if (LOG.isWarnEnabled()) {
LOG.warn("JavaScript doesn't support non-String keys, using toString() on #0", key.getClass().getName());
}
warnedNonString = true;
}
this.value(key.toString(), method);
this.add(":");
this.value(entry.getValue(), method);
if (this.buildExpr) {
this.setExprStack(expr);
}
} this.add("}");
} /**
* Add date to buffer
*/
protected void date(Date date, Method method) {
JSON json = null;
if (method != null)
json = method.getAnnotation(JSON.class);
if (this.formatter == null)
this.formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); DateFormat formatter = (json != null) && (json.format().length() > 0) ? new SimpleDateFormat(json
.format()) : this.formatter;
this.string(formatter.format(date));
} /**
* Add array to buffer
*/
protected void array(Iterator it, Method method) throws JSONException {
this.add("["); boolean hasData = false;
for (int i = 0; it.hasNext(); i++) {
String expr = null;
if (this.buildExpr) {
expr = this.expandExpr(i);
if (this.shouldExcludeProperty(expr)) {
it.next();
continue;
}
expr = this.setExprStack(expr);
}
if (hasData) {
this.add(',');
}
hasData = true;
this.value(it.next(), method);
if (this.buildExpr) {
this.setExprStack(expr);
}
} this.add("]");
} /**
* Add array to buffer
*/
protected void array(Object object, Method method) throws JSONException {
this.add("["); int length = Array.getLength(object); boolean hasData = false;
for (int i = 0; i < length; ++i) {
String expr = null;
if (this.buildExpr) {
expr = this.expandExpr(i);
if (this.shouldExcludeProperty(expr)) {
continue;
}
expr = this.setExprStack(expr);
}
if (hasData) {
this.add(',');
}
hasData = true;
this.value(Array.get(object, i), method);
if (this.buildExpr) {
this.setExprStack(expr);
}
} this.add("]");
} /**
* Add boolean to buffer
*/
protected void bool(boolean b) {
this.add(b ? "true" : "false");
} /**
* escape characters
*/
protected void string(Object obj) {
this.add('"'); CharacterIterator it = new StringCharacterIterator(obj.toString()); for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
if (c == '"') {
this.add("\\\"");
} else if (c == '\\') {
this.add("\\\\");
} else if (c == '/') {
this.add("\\/");
} else if (c == '\b') {
this.add("\\b");
} else if (c == '\f') {
this.add("\\f");
} else if (c == '\n') {
this.add("\\n");
} else if (c == '\r') {
this.add("\\r");
} else if (c == '\t') {
this.add("\\t");
} else if (Character.isISOControl(c)) {
this.unicode(c);
} else {
this.add(c);
}
} this.add('"');
} /**
* Add object to buffer
*/
protected void add(Object obj) {
this.buf.append(obj);
} /**
* Add char to buffer
*/
protected void add(char c) {
this.buf.append(c);
} /**
* Represent as unicode
*
* @param c character to be encoded
*/
protected void unicode(char c) {
this.add("\\u"); int n = c; for (int i = 0; i < 4; ++i) {
int digit = (n & 0xf000) >> 12; this.add(hex[digit]);
n <<= 4;
}
} public void setIgnoreHierarchy(boolean ignoreHierarchy) {
this.ignoreHierarchy = ignoreHierarchy;
} /**
* If true, an Enum is serialized as a bean with a special property
* _name=name() as all as all other properties defined within the enum.<br/>
* If false, an Enum is serialized as a name=value pair (name=name())
*
* @param enumAsBean true to serialize an enum as a bean instead of as a name=value
* pair (default=false)
*/
public void setEnumAsBean(boolean enumAsBean) {
this.enumAsBean = enumAsBean;
} protected static class JSONAnnotationFinder {
private boolean serialize = true;
private Method accessor;
private String name; public JSONAnnotationFinder(Method accessor) {
this.accessor = accessor;
} public boolean shouldSerialize() {
return serialize;
} public String getName() {
return name;
} public JSONAnnotationFinder invoke() {
JSON json = accessor.getAnnotation(JSON.class);
serialize = json.serialize();
if (serialize && json.name().length() > 0) {
name = json.name();
}
return this;
}
} }

struts2 json 定义全局Date格式的更多相关文章

  1. vue定义全局date过滤器(自定义JS文件模块和Moment.js库)

    自定义dateFormat.js文件模块 dateFormat.js /** * 时间字符串 转 时间戳 * @param {String} time_str 时间字符串(格式"2014-0 ...

  2. 字定义JSON序列化支持datetime格式序列化

    字定义JSON序列化支持datetime格式序列化 由于json.dumps无法处理datetime日期,所以可以通过自定义处理器来做扩展,如: import json from datetime i ...

  3. struts2 json 输出日期格式不正确

    struts2 输出json中 日期出现:2013-12-17T15:57:47 错误格式的数据 原因:struts2 json插件对日期的格式化有问题 解决方法:在实体类的日期的get方法上加注解: ...

  4. webapi返回json格式,并定义日期解析格式

    1.webapi返回json格式 var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferen ...

  5. struts2异常处理,global-results定义全局结果处理

    <global-results>定义全局结果处理 一般发生异常之后 结果返回errHandler 因为errHandler是由<global-exception-mappings&g ...

  6. 使用 JSON.parse 反序列化 ISO 格式的日期字符串, 将返回Date格式对象

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 解决nodejs中json序列化时Date类型默认为UTC格式

    在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 上面只是一个例子,下面我用一个更具体化的例子来展示一个这个情况,我们在开发WEB项目中,经常用到Express组件, 我 ...

  8. 解决nodejs中json序列化时Date类型为UTC格式

    在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 zhupengfei@DESKTOP-HJASOE3 MINGW64 /d/MyProject/exp2 $ node ...

  9. Struts2中防止表单重复提交,global-results定义全局结果处理

    1.在表单中加入<s:token/>标签 2.在动作类中加入token的拦截器 <!--如果单单写 name="token" 会丧失 defaultStack 拦 ...

随机推荐

  1. hadoop 2.0--YARN

    从2012年8月开始Apache Hadoop YARN(YARN = Yet Another Resource Negotiator)成了Apache Hadoop的一项子工程.自此Apache H ...

  2. windows“画图”工具用法

    图片编辑工具不少,photoshop功能强大,但是并不是那么容易掌握.而且,倘若一个简单的图片处理问题就使用这么强大的工具,有点“杀鸡焉用牛刀”的意思,要知道只打开photoshop就需要一段等待时间 ...

  3. ASP.NET MVC轻教程 Step By Step 5——初识表单

    上一节我们将留言列表显示在Index视图里了,现在该添加一个留言的表单,好让用户自己添加留言. 首先在HomeController中添加一个名为“Write”的动作方法. public ActionR ...

  4. HTML5峰会小记

    5259月228日,在大连理工的伯川图书馆举办了一次HTML5峰会,小记一下这次峰会的内容. 名为HTML5峰会,其本质就是一次各大赞助商的轮番登场,产品介绍间隙插播一下HTML5.但是并不影响这次峰 ...

  5. 关于64位Win7/Win 8 下怎么学习汇编语言

    我看有许多同学用Win 7/Win 8 学习汇编,现在好多人的内存升级了都用64位系统了,但是64位W7没有自带的DEBUG和MASM. 1.首先下载DOSBOX,(下面附带地址)它的作用就是让你在6 ...

  6. Hadoop 学习笔记 (十一) MapReduce 求平均成绩

    china:张三 78李四 89王五 96赵六 67english张三 80李四 82王五    84赵六 86math张三 88李四 99王五 66赵六 77 import java.io.IOEx ...

  7. Contest20140711 loop 数论

    loop|loop.in|loop.out 题目描述: 有N个点. 现在重复这样的操作: 随机找一个出度为0的点p1,随机找一个入度为0的点p2,连一条有向边从p1指向p2.直到没有出度为0的点. 统 ...

  8. [BZOJ 1336] [Balkan2002] Alien最小圆覆盖 【随机增量法】

    题目链接:BZOJ - 1336 题目分析 最小圆覆盖有一个算法叫做随机增量法,看起来复杂度像是 O(n^3) ,但是可以证明其实平均是 O(n) 的,至于为什么我不知道= = 为什么是随机呢?因为算 ...

  9. 应用安全技术趋势之 Top 5

    而今,大多数应用都依赖于像入侵防护系统(Instrusion Prevention System)和 Web 应用防火墙(Web Application Firewall,以下全文简称 WAF)这样的 ...

  10. iOS-NSTimer-pause-暂停-引用循环

    7月26日更新: 今天更新的主要目的是因为暂停!!!! 注:不推荐使用,并不是这样有错,而是因为这样写代码的规范问题,代码要有可读性,遵循代码即文档,使用暂停在团队合作中可能会带来误会,非必要不建议使 ...