背景说明: 本示例中用的是fastJson来解析具体的事务;

简介: 

1. 目前支持一个json普通对象字符串反序列化,数组对象反序列化,普通对象中含有其他对象或者数组对象的反序列化;

2.支持对List嵌套的反序列化,比如将[ [XXXX],[XXXX]  ] 反序列化成为 List<List<?>>;

问题:

        当json数据遇到嵌套,我找了一段时间都没有找到很好的解决办法,所以自己写了这个工具来解析相关json字符串,并使之还原为一个对象;

        这时候如果直接反序列化可能报错:not close json text, token : ,

        比如遇到如下json数据:

              

[
    {
        "id": 123, 
        "name": 1111, 
        "point": [
            {
                "x": 1, 
                "y": 1
            }, 
            {
                "x": 2, 
                "y": 2
            }
        ]
    }, 
    {
        "id": 123, 
        "name": 1111, 
        "points": [
            {
                "x": 5, 
                "y": 1
            }, 
            {
                "x": 562, 
                "y": 2
            }, 
            {
                "x": 20, 
                "y": 26
            }
        ]
    }, 
    {
        "id": 123, 
        "name": 1111, 
        "points": [
            {
                "x": 9, 
                "y": 132
            }, 
            {
                "x": 2, 
                "y": 2
            }
        ]
    }
]



                       对应的类如下:

                             

public class A {
    public String id;
    public String name;
    List<Point> points;
}
public class Point {
    public Double x;
    public Double y;
}



由上面的json数据,可以看到:

               整个json数据实际上是一个类A的数组;数组A的属性points实际上是一个类Point的数组;在这样的情况下,很多json工具并不能够直接进行反序列化;

如此,huitoukest编写了工具来解决这类问题,工具如下:

         编写一个支持类Annotation:

                   

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 指定当前json字符串对应反序列化的方式JsonPropertyType
 * JsonList,JsonObject,Base,Transient
 * 当JsonPropertyType.Base的时候,将会按照默认识别的类型使用,即此时的cls属性不会生效
 * JsonList,JsonObject表示此对象是一个json<span style="font-family: Arial, Helvetica, sans-serif;">对象数组或者</span>对象;
 * 选择Transient的时候,cls属性不会生效,此属性不进行反序列化操作
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonFieldProperty{
	
	/**
	 * 指定一个类型是JsonPropertyType的,表现为JsonPropertyType=默认为JsonPropertyType.Base的Annotation
	 * @return
	 */
	JsonPropertyType JsonPropertyType() default JsonPropertyType.Base;
	/**
	 * 指定一个类型是Class的,表现为cls=默认为String.class的Annotation
	 * @return
	 */
	Class cls() default String.class;
	/**
     * 指定当前属性的类型
     *
     */
    public enum JsonPropertyType{   	  
    	JsonList,JsonObject,Base,Transient;
    	};
     
    	
}



编写一个工具类:

   

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;


public class JsonUtils_wg {
	/**
	 * bean中的属性只能够是如下几种包装类型;
	 * 已经用Annotation注释的list和object;
	 */
	private static final String type_boolean="class java.lang.Boolean",
			   type_date="class java.util.Date",
			   type_float="class java.lang.Float",
			   type_double="class java.lang.Double",
			   type_long="class java.lang.Long",
			   type_integer="class java.lang.Integer",
			   type_string="class java.lang.String";
	/**
	 * 查看一个字符串是否是一[开头,即是否有可能是数组;
	 */
	private static final Pattern pattern = Pattern.compile("^([\\s]{0,}\\[).*");

	/**
	 * 
	 * @param jsonString json字符串
	 * @param cls 需要转换的class类
	 * @return
	 * @throws IllegalArgumentException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static List<? extends Object> parseToArray(String jsonString,Class cls) throws IllegalAccessException, IllegalArgumentException, InstantiationException{
		 JSONArray jsonArr = JSON.parseArray(jsonString);
		 List<Object> list=new ArrayList<Object>();
		 Object o;
		 for(int i=0;i<jsonArr.size();i++){
			 String jarString=jsonArr.getString(i);
			 Matcher matcher = pattern.matcher(jarString);
			 if(matcher.find()){//如果数组中包含的仍然是一个数组
				 try{
				 List<?> tmp=parseToArray(jarString, cls);
				 list.add(tmp);
				 }catch(JSONException e){
					 o=parseToObject(jarString, cls);				 
					 list.add(o);
				 }
			 }else{
				 o=parseToObject(jarString, cls);				 
				  list.add(o);
			 }		   			 		 
		 }
		 return list;
   }
	
	public static Object parseToObject(String string,Class cls) throws InstantiationException, IllegalAccessException{
		Object o=cls.newInstance();
		 JSONObject jsonObj=(JSONObject) JSONObject.parse(string);
			 Field[] fields=cls.getFields();
			 for(int j=0;j<fields.length;j++){
				 Field field=fields[j];
				 field.setAccessible(true);
				 Annotation[] annotations=field.getAnnotations();
				 //为自定义的Annotation赋值
				 JsonFieldProperty jsonFieldProperty=null;
				 for(int a=0;a<annotations.length;a++){
					 if(annotations[a] instanceof JsonFieldProperty){
						 jsonFieldProperty=(JsonFieldProperty)annotations[a];
						 break;
					 }
				 }
				 Object tmp=null;
				 if(jsonFieldProperty==null||jsonFieldProperty.JsonPropertyType()==null||jsonFieldProperty.JsonPropertyType()==JsonPropertyType.Base){
					 tmp=jsonObj.get(field.getName());
					 String typeString=field.getGenericType().toString();
					 if(tmp!=null)
					 {
					   		if(typeString.equals(type_boolean)){
					   			field.set(o, jsonObj.getBoolean(field.getName()));
					   		}else if(typeString.equals(type_date)){
					   			field.set(o, jsonObj.getDate(field.getName()));						  
							}else if(typeString.equals(type_integer)){
								field.set(o, jsonObj.getInteger(field.getName()));
							}else if(type_long.equals(typeString)){
								field.set(o, jsonObj.getLong(field.getName()));
							}else if(typeString.equals(type_float)){
								field.set(o, jsonObj.getFloat(field.getName()));
							}else if(typeString.equals(type_double)){
								field.set(o, jsonObj.getDouble(field.getName()));
							}else if(typeString.equals(type_string)){
								field.set(o, jsonObj.getString(field.getName()));
							}else{
								field.set(o, tmp);
								}
					}
				 }else if(jsonFieldProperty.JsonPropertyType()==JsonPropertyType.JsonObject){
					 tmp=jsonObj.getString(field.getName());
					 if(tmp!=null)
					 field.set(o,parseToObject(tmp.toString(), jsonFieldProperty.cls()));
				 }else if(jsonFieldProperty.JsonPropertyType()==JsonPropertyType.JsonList){
					 tmp=jsonObj.getString(field.getName());
					 if(tmp!=null)
					 field.set(o,parseToArray(tmp.toString(), jsonFieldProperty.cls()));
				 }					 				 
			 }
		 return o;
	}
}



使用方法,在需要将一个json字符串转换为List或者普通对象的时候,

1.加上JsonFieldProperty注解,

2.之后使用JsonUtils_wg工具来进行相应的转换即可:

                

@JsonFieldProperty(JsonPropertyType=JsonPropertyType.JsonList,cls=Point.class)
    public List<Point> points;



注意:

         1.本例中使用的fasjson作为解析类,需要的童鞋可以自己改为相应的类;

         2.此序列化是通过属性的名称和注解来完成了,所以属性最好设置为public,可以不要getter和setter方法,如果setter和getter方法中名字和属性不对应的需要注意可能的错误;

         3. 此工具只支持包装类和普通对象以及对象数组,不支持基础数据类型,并且限定包装类为Date,String,Long,Integer,Double,Float,Boolean这几种,不然可能会出现问题

    4.如果那个大神有空将通过方法来完成反序列化的功能实现,然后留言给我一个连接那就更好了...