利用Java反射机制将Json格式字符串反射为 Bean List

前面提到过Strtus2在2.1.6以后就将Json格式整合到Strtus中了,可见到struts-json-plugin,在Struts的文档里面有下面一段例子:

Example

Setup Action

This simple action has some fields:

Example:

import java.util.HashMap;
import java.util.Map;

import com.opensymphony.xwork2.Action;

public class JSONExample {
    private String field1 = "str";
    private int[] ints = {10, 20};
    private Map map = new HashMap();
    private String customName = "custom";

    //'transient' fields are not serialized
    private transient String field2;

    //fields without getter method are not serialized
    private String field3;

    public String execute() {
        map.put("John", "Galt");
        return Action.SUCCESS;
    }

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public int[] getInts() {
        return ints;
    }

    public void setInts(int[] ints) {
        this.ints = ints;
    }

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    @JSON(name="newName")
    public String getCustomName() {
        return this.customName;
    }

Write the mapping for the action

  1. Add the map inside a package that extends "json-default"
  2. Add a result of type "json"

Example:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

  <package name="example"  extends="json-default">
     <action name="JSONExample" class="example.JSONExample">
        <result type="json"/>
     </action>
  </package>

</struts>

JSON example output

{  
   "field1" : "str", 
   "ints": [10, 20],
   "map": {
       "John":"Galt"
   },
   "newName": "custom"
}

如例子中所示,根据配置Strtus会通过JsonUtil将对象转换为Json格式的字符串,然后通过流返回给客户端,但当Ext返回Json对象的时候,JsonUtil的反序列化功能似乎逊色了许多,大概看了一下源代码JsonUtil中能将Json格式的对象集合转为List<Map<Objcet,Object>>这种格式,而不能映射到实体类,现实中Json的工具还有许多,例如google的Json工具就提供了fromJson的方法,在这里我只是利用Java反射写了一个对简单类型反射的工具类,说了这么多废话,切入正题:

public static <T> List<T> fromJson(String json, Class<T> cls,
			SimpleDateFormat sdf) {
		List<T> result = new ArrayList<T>();
		try {
			Map<String, Method> methodMap = new HashMap<String, Method>();
			Method[] methods = cls.getMethods();
			for (Method m : methods) {
				String name = m.getName().toUpperCase();
				if (name.startsWith("SET") || name.startsWith("IS")) {
					methodMap.put(name.substring(3), m);
				}
			}
			List<Map<Object, Object>> list = (List<Map<Object, Object>>) JSONUtil
					.deserialize(json);
			for (Map<Object, Object> map : list) {
				Object o = cls.newInstance();
				Iterator<Entry<Object, Object>> itr = map.entrySet().iterator();
				while (itr.hasNext()) {
					Entry<Object, Object> entry = itr.next();
					String key = entry.getKey().toString().toUpperCase();
					if (methodMap.containsKey(key)) {
						Method _m = methodMap.get(key);
						Class<?> c = _m.getParameterTypes()[0];

						if (c.getName().equals("int")) {
							_m.invoke(o, Integer.parseInt(entry.getValue()
									.toString()));
						} else if (c.getName().equals("long")) {
							_m.invoke(o,
									Long.parseLong(entry.getValue().toString()));
						} else if (c == Integer.class) {
							_m.invoke(o, (Integer) Integer.parseInt(entry
									.getValue().toString()));
						} else if (c == Long.class) {
							_m.invoke(o, (Long) Long.parseLong(entry.getValue()
									.toString()));
						} else if (c == String.class) {
							_m.invoke(o, entry.getValue().toString());
						} else if (c == Date.class) {
							String date = entry.getValue().toString();
							date = date.replaceFirst("T", " ");
							_m.invoke(o, sdf.parse(date));
						}
					}
				}
				if (o != null) {
					System.out.println("sss");
					result.add((T) o);
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;

	}

主要是找到SET方法然后将对应的属性设置进去,而对应的属性则是根据判断参数类型来进行的,再看下面这一句
String date = entry.getValue().toString();
date = date.replaceFirst("T", " ");

Strtus2的Json Plugin似乎有一个问题目前还没有搞清楚,Strtus在将java.util.Date类型时间格式
2011-07-13 14:24:31
转换为Json字符串的时候变成了这个样子

2011-07-13T14:24:31
所以当提交回来的时候如果是这种时间格式是不能转换的,于是有了上面把T替换为“ ”的操作。

明天再研究一下到底是什么原因导致时间类型转换的异常。

你可能感兴趣的:(java,json,bean,String,object,struts)