基于org.json的快速构建和解析json文本扩展工具

之前做过一个项目需要使用json来传输数据,我用的是org.json,但是其构造和解析方法过于繁琐,想到之前解析xml时用的simpleXml可以通过注解的方式构造和解析xml文本,

我就参考simpleXml,利用java的反射机制做了一个基于org.json的工具包,这个工具同样可以通过注解来构造json。


首先是一个接口,这个接口是个标记,表名一个类可以使用这个工具转换json

package dikaros.json.annotation;

/**
 * 动态转换标记<br>
 * 表示该实例类可以被动态转换成json信息<br>
 * @author Dikaros
 *
 */
public interface Jsonable {

}


接下来是声明的注解JsonParam


package dikaros.json.annotation;

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

/**
 * JsonParam 标准类型注解用在类的基本属性前<br>
 * 在生成json文本后为键值对的key<br>
 * @author Dikaros
 *
 */
//注解会在class字节码文件中存在,在运行时可以通过反射获取到  
@Retention(RetentionPolicy.RUNTIME) 
public @interface JsonParam {
	/**
	 * json文本 键
	 * @return
	 */
	public String name() default "";
	
}


注解JsonListParam

package dikaros.json.annotation;

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

/**
 * JsonParam 标准类型注解用在类的基本属性前<br>
 * 在生成json文本后为键值对的key<br>
 * className表示数组类型或集合的泛型如<code>String.class</code><br>
 * 枚举类型TYPE表示数组类型ARRAY表示数组,例如int[], LIST表示集合,例如java.util.List<br>
 * 
 * @author Dikaros
 * @see TYPE
 * 
 */
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonListParam {
	public String name() default "";

	/**
	 * 数组类型或集合泛型
	 * @return
	 */
	public Class contentClassName();

	/**
	 * 设置是集合还是数组
	 * @return <code>TYPE.ARRAY</code>或<code>TYPE.LIST</code>
	 * @see TYPE
	 */
	public TYPE classType() default TYPE.LIST;

	/**
	 * 多数据类型<br>
	 * ARRAY表示数组,例如int[]<br>
	 * LIST表示集合,例如java.util.List<br>
	 * 默认为LIST
	 * 
	 * @author Dikaros
	 * 
	 */
	public enum TYPE {
		ARRAY, LIST
	};
}

然后就是主要的工具类了,由于这个类是基于org,json的,所以相关的org.json大家可以从其他地方下载,另外本文还附带了一个jar包,需要的可以下载

package dikaros.json;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import dikaros.json.annotation.JsonListParam;
import dikaros.json.annotation.JsonParam;
import dikaros.json.annotation.Jsonable;
import dikaros.json.annotation.JsonListParam.TYPE;
import dikaros.org.json.JSONArray;
import dikaros.org.json.JSONException;
import dikaros.org.json.JSONObject;
import dikaros.org.json.JSONStringer;

/**
 * org.json扩展<br>
 * 将类构造成简单的json文本<br>
 * 注意:构造的类需要实现Jsonable接口,并且是标准的JavaBean<br>
 * 原理:通过反射机制获取需要转换成json对象的注解,根据注解的内容生成key<br>
 * 由于注解是添加在变量上的,如果类拥有标准get和set方法,则通过反射获取<br>
 * 并执行这些方法即可当作value<br>
 * 建议:将一些类型改变为基本类型,如java.util.Date用long来表示
 * 
 * @author Dikaros
 * @see Jsonable
 * @see JsonParam
 * @see JsonListParam
 */
public class JsonExtendedUtil {

	/**
	 * 构造一个对象的json
	 * 
	 * @param object
	 *            需要转换成json的对象,需要实现Jsonable接口
	 * @return json文本
	 * @throws Exception
	 */
	public static String generateJson(Object object) throws Exception {
		JSONStringer stringer = new JSONStringer();
		stringer.array();
		generateObjectMessage(object, stringer);
		stringer.endArray();
		return stringer.toString();
	}

	/**
	 * 构造json<br>
	 * 原理:通过反射机制获取注解并将其作为key,再调用field的get方法即可得到value
	 * 
	 * @param object
	 *            需要转换成json的对象,需要实现Jsonable接口
	 * @param stringer
	 *            org.json的json构造器
	 * @throws Exception
	 */
	private static void generateObjectMessage(Object object,
			JSONStringer stringer) throws Exception {
		// 如果object没有实现Jsonable接口,则抛出异常
		if (!(object instanceof Jsonable)) {
			throw new Exception("不支持的类型格式,是否忘记了实现JsonAble接口");
		}
		// 开始构造json对象
		stringer.object();
		Class clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			if (field.isAnnotationPresent(JsonParam.class)) {
				JsonParam jsonParam = field.getAnnotation(JsonParam.class);
				// json键
				stringer.key(jsonParam.name());
				Method method = getFieldMethod(clazz, field);
				Object value = method.invoke(object, new Object[] {});
				// json值
				stringer.value(value);
			} else if (field.isAnnotationPresent(JsonListParam.class)) {
				// System.out.println("list");
				JsonListParam jsonListParam = field
						.getAnnotation(JsonListParam.class);
				// 字段名称,根据字段名称获取其对应的get方法
				Method method = getFieldMethod(clazz, field);

				Object value = method.invoke(object, new Object[] {});
				if (value == null) {
					continue;
				}
				if (jsonListParam.classType() == TYPE.ARRAY) {

					Array.getLength(value);
					// 调用get方法
					stringer.key(jsonListParam.name());
					// 集合的键
					stringer.array();

					// 集合字段
					for (int i = 0; i < Array.getLength(value); i++) {
						Object listItem = Array.get(value, i);
						// 如果集合是JsonAble的实例则调用此函数
						if ((listItem instanceof Jsonable)) {
							generateObjectMessage(listItem, stringer);
						}
						// 如果集合不是JsonAble的实例
						else if (isBaseType(listItem)) {
							stringer.value(listItem);
						} else {
							throw new Exception("集合元素类型不支持,请将集合内元素实现JsonAble接口");
						}
					}
					// 集合结束
					stringer.endArray();
				} else if (jsonListParam.classType() == TYPE.LIST) {
					// 调用get方法
					stringer.key(jsonListParam.name());
					// 集合的键
					stringer.array();

					// 集合字段
					List list = (List) value;
					for (Object listItem : list) {
						// 如果集合是JsonAble的实例则调用此函数
						if ((listItem instanceof Jsonable)) {
							generateObjectMessage(listItem, stringer);
						}
						// 如果集合不是JsonAble的实例
						else if (isBaseType(listItem)) {
							stringer.value(listItem);
						} else {
							throw new Exception("集合元素类型不支持,请将集合内元素实现JsonAble接口");
						}
					}
					// 集合结束
					stringer.endArray();
				}

			}
		}
		// json对象结束
		stringer.endObject();
	}

	/**
	 * 判断对象是否是基本类型
	 * 
	 * @return true是,false 不是
	 */
	private static boolean isBaseType(Object obj) {
		boolean result = false;
		if ((obj instanceof Integer) || (obj instanceof Byte)
				|| (obj instanceof Double) || (obj instanceof Boolean)
				|| (obj instanceof String) || (obj instanceof Short)
				|| (obj instanceof Long) || (obj instanceof Character)
				|| (obj instanceof Float)) {
			result = true;
		}

		return result;
	}

	/**
	 * 获取JavaBean字段的get方法
	 */
	private static Method getFieldMethod(Class clazz, Field field)
			throws Exception {
		String fieldName = field.getName();
		fieldName = fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
		Method method = null;
		try {
			if (field.getType() == Boolean.class) {
				method = clazz.getMethod("is" + fieldName, null);
			} else {
				method = clazz.getMethod("get" + fieldName, null);
			}
		} catch (NoSuchMethodException e) {
			throw new Exception("不是标准的JavaBean,注意JavaBean的格式");
		}
		return method;
	}

	/**
	 * 获取JavaBean字段的set方法
	 */
	@SuppressWarnings("unchecked")
	private static Method setFieldMethod(Class clazz, Field field)
			throws Exception {
		String fieldName = field.getName();
		fieldName = fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
		Method method = null;
		try {
			// System.out.println("set---" + fieldName);
			method = clazz.getMethod("set" + fieldName,
					new Class[] { field.getType() });
		} catch (NoSuchMethodException e) {
			throw new Exception("不是标准的JavaBean,注意JavaBean的格式");
		}
		return method;
	}

	public static Object compileJson(Class clazz, String jsonFile)
			throws Exception {
		JSONArray array = new JSONArray(jsonFile);
		Object object = null;
		if (array.length() > 0) {
			JSONObject jsonObject = array.getJSONObject(0);
			object = clazz.newInstance();
			getObjectFromJsonFile(object, jsonObject.toString());
		}

		return object;
	}

	/**
	 * 解析Json<br>
	 * 原理:传入Object获取其类型,通过其类型的注解调用属性的set方法更改Object的值<br>
	 * 注意:该方法的传入json是一个JSONObject型的
	 * 
	 * @param jsonable
	 *            待转换的类
	 * @param jsonFile
	 *            需要解析的jsonFile
	 * @throws Exception
	 */
	private static void getObjectFromJsonFile(Object jsonable, String jsonFile)
			throws Exception {
		if (!(jsonable instanceof Jsonable)) {
			throw new Exception("不支持的类型格式,是否忘记了实现JsonAble接口");
		}
		// 获取class
		Class clazz = jsonable.getClass();
		JSONObject obj = new JSONObject(jsonFile);
		// 获取类所有的属性
		Field[] fields = clazz.getDeclaredFields();
		// 遍历所有的属性
		for (Field field : fields) {
			/*
			 * 如果属性中存在JsonParam的注解 从JsonFile中获取内容 通过反射机制调用set方法更新属性
			 */
			if (field.isAnnotationPresent(JsonParam.class)) {
				JsonParam jsonParam = field.getAnnotation(JsonParam.class);
				String keyName = jsonParam.name();
				Object value = obj.get(keyName);
				Method method = setFieldMethod(clazz, field);
				// 调用set方法更新属性
				method.invoke(jsonable, new Object[] { value });

			}
			/*
			 * 如果属性中存在JsonListParam的注解 从JsonFile中获取内容 判断多值类型是集合还是数组
			 * 根据类型采用不同的方法更新属性
			 */
			else if (field.isAnnotationPresent(JsonListParam.class)) {
				JsonListParam jsonListParam = field
						.getAnnotation(JsonListParam.class);
				// 获取键
				String keyName = jsonListParam.name();

				JSONArray jArray = null;
				/*
				 * 判断有没有这样的keyName 如果没有,跳过进行下一次循环
				 */
				try {
					jArray = obj.getJSONArray(keyName);
				} catch (Exception e) {
					continue;
				}
				if (!(field.getType().equals(List.class))
						&& !field.getType().isArray()) {
					throw new Exception("类型错误,类型不是List的实例");
				}
				Method method = setFieldMethod(clazz, field);
				TYPE classType = jsonListParam.classType();
				/*
				 * 如果是集合 构建集合 递归调用此方法进行设置
				 */
				if (classType == TYPE.LIST) {
					List list = new ArrayList<>();
					for (int i = 0; i < jArray.length(); i++) {
						JSONObject item = jArray.getJSONObject(i);
						Class itemClass = jsonListParam.contentClassName();
						Object itemObject = itemClass.newInstance();
						if (itemObject instanceof Jsonable) {
							getObjectFromJsonFile(itemObject, item.toString());
							list.add(itemObject);
						} else if (isBaseType(itemObject)) {
							list.add(jArray.get(i));
						}
					}
					method.invoke(jsonable, new Object[] { list });
				}
				/*
				 * 如果是数组 根据JSONArray大小构建数组 递归调用此方法进行设置
				 */
				else if (classType == TYPE.ARRAY) {

					// Object[] items = new Object[jArray.length()];
					Object items = Array.newInstance(
							jsonListParam.contentClassName(), jArray.length());
					for (int i = 0; i < jArray.length(); i++) {
						Class itemClass = jsonListParam.contentClassName();
						Object itemObject = itemClass.newInstance();
						if (itemObject instanceof Jsonable) {
							JSONObject item = jArray.getJSONObject(i);
							getObjectFromJsonFile(itemObject, item.toString());
							// items[i] = itemObject;
							Array.set(items, i, itemObject);
						} else if (isBaseType(itemObject)) {
							Array.set(items, i, jArray.get(i));

						}
					}
					System.out.println("method--->" + method.getName() + ":"
							+ method.getParameterTypes()[0]);
					method.invoke(jsonable, new Object[] { items });
				}

			}
		}

	}

	/**
	 * 获取long值
	 * 
	 * @param jsonFile
	 * @param param
	 * @return
	 */
	public static long getLongParam(String jsonFile, String param) {
		long result = 0;
		JSONObject obj;
		JSONArray array;

		try {
			array = new JSONArray(jsonFile);
			if (array.length() > 0) {
				obj = array.getJSONObject(0);
				result = obj.getLong(param);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 获取boolean值
	 * 
	 * @param jsonFile
	 * @param param
	 * @return
	 */
	public static boolean getBooleanParam(String jsonFile, String param) {
		boolean result = false;
		JSONObject obj;
		JSONArray array;

		try {
			array = new JSONArray(jsonFile);
			if (array.length() > 0) {
				obj = array.getJSONObject(0);
				result = obj.getBoolean(param);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 获取指定字段的内容
	 * 
	 * @param jsonFile
	 * @param param
	 * @return
	 */
	public static String getParam(String jsonFile, String param) {
		String result = null;
		JSONObject obj;
		JSONArray array;

		try {
			array = new JSONArray(jsonFile);
			if (array.length() > 0) {
				obj = array.getJSONObject(0);
				result = obj.getString(param);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 从json文件中获取整型值
	 * 
	 * @param jsonFile
	 * @param param
	 * @return
	 */
	public static int getIntParam(String jsonFile, String param) {
		int result = -1;
		JSONObject obj;
		JSONArray array;

		try {
			array = new JSONArray(jsonFile);
			if (array.length() > 0) {
				obj = array.getJSONObject(0);
				result = obj.getInt(param);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 构建 传输信息
	 * 
	 * @param map
	 * @return
	 */
	public static String constructMapJson(HashMap map) {
		Set set = map.keySet();
		JSONStringer jsonStringer = new JSONStringer();
		try {
			jsonStringer.array();
			jsonStringer.object();

			for (Iterator iterator = set.iterator(); iterator.hasNext();) {
				String key = (String) iterator.next();
				jsonStringer.key(key);
				jsonStringer.value(map.get(key));
			}
			jsonStringer.endObject();
			jsonStringer.endArray();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return jsonStringer.toString();
	}


}

下面有一个实例,这个实例演示怎么使用这个工具

假定有一个类Person,注意,由于利用的是java的反射机制,所以这个类一定要是标准的JavaBean,被注解的属性必须有getter和setter方法。

package dikaros.example;

import java.util.Arrays;
import java.util.List;

import dikaros.json.annotation.JsonListParam;
import dikaros.json.annotation.JsonParam;
import dikaros.json.annotation.Jsonable;
import dikaros.json.annotation.JsonListParam.TYPE;

/**
 * 示例对象
 * @author Dikaros
 *
 */
public class Person implements Jsonable{
	public Person(String name, String gender, int age, String cityName) {
		this.name = name;
		this.gender = gender;
		this.age = age;
		this.cityName = cityName;
	}
	
	public Person() {
	}
	
	@JsonParam(name="name")
	String name;
	
	@JsonParam(name="gender")
	String gender;
	
	@JsonParam(name="age")
	int age;
	
	@JsonParam(name="cityName")
	String cityName;
	
	@JsonListParam(name="friends",contentClassName=Person.class,classType = TYPE.LIST)
	List<Person> friend;
	
	@JsonListParam(name="phones",contentClassName=String.class,classType = TYPE.ARRAY)
	String [] phones;
	
	
	/**
	 * @return name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name 要设置的 name
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return gender
	 */
	public String getGender() {
		return gender;
	}
	/**
	 * @param gender 要设置的 gender
	 */
	public void setGender(String gender) {
		this.gender = gender;
	}
	/**
	 * @return cityName
	 */
	public String getCityName() {
		return cityName;
	}
	/**
	 * @param cityName 要设置的 cityName
	 */
	public void setCityName(String cityName) {
		this.cityName = cityName;
	}
	/**
	 * @return age
	 */
	public int getAge() {
		return age;
	}
	/**
	 * @param age 要设置的 age
	 */
	public void setAge(int age) {
		this.age = age;
	}
	/**
	 * @return friend
	 */
	public List<Person> getFriend() {
		return friend;
	}
	/**
	 * @param friend 要设置的 friend
	 */
	public void setFriend(List<Person> friend) {
		this.friend = friend;
	}

	/* (非 Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "Person [name=" + name + ", gender=" + gender + ", age=" + age
				+ ", cityName=" + cityName + ", friend=" + friend + ", phones="
				+ Arrays.toString(phones) + "]";
	}

	/**
	 * @return phones
	 */
	public String[] getPhones() {
		return phones;
	}

	/**
	 * @param phones 要设置的 phones
	 */
	public void setPhones(String[] phones) {
		this.phones = phones;
	}

	
	
}

下面是调用

package dikaros.example;

import java.util.ArrayList;

import dikaros.json.JsonExtendedUtil;

public class Example {
	public static void main(String[] args) throws Exception {
		Person person = new Person("老王", "男", 20, "长沙");
		String[] phones ={"13000000000","14000000000"};
		person.setPhones(phones);
		ArrayList<Person> friends = new ArrayList<>();
		friends.add(new Person("A妹子", "女", 19, "江西"));
		friends.add(new Person("B妹子", "女", 20, "湖北"));
		person.setFriend(friends);
		String jsonFile = JsonExtendedUtil.generateJson(person);
		System.out.println(jsonFile);
		
		Person person2 = (Person) JsonExtendedUtil.compileJson(Person.class, jsonFile);
		System.out.println(person2);
	}
}

输出结果

[{"name":"老王","gender":"男","age":20,"cityName":"长沙","friends":[{"name":"A妹纸","gender":"女","age":19,"cityName":"江西"},{"name":"B妹纸","gender":"女","age":20,"cityName":"湖北"}],"phones":["13000000000","14000000000"]}]
Person [name=老王, gender=男, age=20, cityName=长沙, friend=[Person [name=A妹纸, gender=女, age=19, cityName=江西, friend=null, phones=null], Person [name=B妹纸, gender=女, age=20, cityName=湖北, friend=null, phones=null]], phones=[13000000000,14000000000]]

我这里有整合了org.json的工具包,需要的可以下载,顺便换点积分 下载工具



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值