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

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

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


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

package dikaros.json.annotation;

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


接下来是声明的注解JsonParam


package dikaros.json.annotation;

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

/**
 * JsonParam 标准类型注解用在类的基本属性前
* 在生成json文本后为键值对的key
* @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 标准类型注解用在类的基本属性前
* 在生成json文本后为键值对的key
* className表示数组类型或集合的泛型如String.class
* 枚举类型TYPE表示数组类型ARRAY表示数组,例如int[], LIST表示集合,例如java.util.List
* * @author Dikaros * @see TYPE * */ // 注解会在class字节码文件中存在,在运行时可以通过反射获取到 @Retention(RetentionPolicy.RUNTIME) public @interface JsonListParam { public String name() default ""; /** * 数组类型或集合泛型 * @return */ public Class contentClassName(); /** * 设置是集合还是数组 * @return TYPE.ARRAYTYPE.LIST * @see TYPE */ public TYPE classType() default TYPE.LIST; /** * 多数据类型
* ARRAY表示数组,例如int[]
* LIST表示集合,例如java.util.List
* 默认为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扩展
* 将类构造成简单的json文本
* 注意:构造的类需要实现Jsonable接口,并且是标准的JavaBean
* 原理:通过反射机制获取需要转换成json对象的注解,根据注解的内容生成key
* 由于注解是添加在变量上的,如果类拥有标准get和set方法,则通过反射获取
* 并执行这些方法即可当作value
* 建议:将一些类型改变为基本类型,如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
* 原理:通过反射机制获取注解并将其作为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
* 原理:传入Object获取其类型,通过其类型的注解调用属性的set方法更改Object的值
* 注意:该方法的传入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 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 getFriend() {
		return friend;
	}
	/**
	 * @param friend 要设置的 friend
	 */
	public void setFriend(List 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 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的工具包,需要的可以下载,顺便换点积分 下载工具



你可能感兴趣的:(Android,JAVA)