自實現 XML 與 對象 間的自動轉換

在java中,解析、分裝xml是一件很是「麻煩」的事。咱們經常須要寫大量的代理來解析不一樣的XML文件,而後將解析結果賦值給相關對象,便於更好的使用;或者將相關對象轉換成XML格式進行輸出。爲了減去這繁瑣的操做,筆者經過反射、註解的功能來實現 XML 與 JAVA對象 的相互轉換。 java

同時,可能存在協議的變更,某些xml標籤可能不在返回,這裏也提供經過註解,快速屏蔽bean中某些屬性的解析和分裝。大大提升了轉換的靈活度,以及便於最小程度的改動現有代碼。 git

XML ——> bean 數組

/**
	 * 解析xml
	 * @param c 目標對象的Class類
	 * @param parentObj 對象的父類,主要用於將對象set到父類中。即,遞歸地將c目標對象中的各個屬性對象進行set操做,使c目標對象屬性值爲解析結果。
	 * @param isCollection 是不是Collection。若是目標對象包含Collection,則定義Class的時候,須要將Collection初始化
	 * @param element 當前對象的Xml層對應的Element
	 * @return 封裝好的c對象實例
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Object parseXml(Class c, Object parentObj, boolean isCollection, Element element)
			throws Exception
	{
		Object currentObj = null;
		Element currentElement = element;
		if (parentObj == null)
		{
			currentObj = c.newInstance();
		}
		else if(isCollection)
		{
			currentObj = parentObj;
		}
		else
		{
			//經過c獲取className,並將className對象set到parentObj中
			
			String[] strs = c.getName().split("\\.");
			strs = strs[strs.length - 1].split("\\$");
			String className = strs[strs.length - 1];
			element = currentElement.element(className.toUpperCase());
			if(element == null)
			{
				throw new Exception("parseXml Error. target:" + className + " is not exists");
			}
			currentObj = c.newInstance();
			String setMethod = "set" + className.substring(0, 1).toUpperCase() + className.substring(1);
			Method method = parentObj.getClass().getDeclaredMethod(setMethod, c);
			method.invoke(parentObj, new Object[]{currentObj});
			
		}
		Field[] fieldArray = c.getDeclaredFields();
		for (Field field : fieldArray)
		{
			//若屬性標示爲無需解析,則continue
			if(field.isAnnotationPresent(XmlTransformAnnotation.class))
			{
				XmlTransformAnnotation xmlAnnotation = (XmlTransformAnnotation)field.getAnnotation(XmlTransformAnnotation.class);
				String isParse = xmlAnnotation.value();
				if(XmlTransformAnnotation.FLASE.equals(isParse))
				{
					continue;
				}
			}
			
			Class basicType = getBasicType(field.getType());
			if (basicType != null)
			{
				//屬性爲基本類型(包括:String、Integer、Byte、Short、Long、Float、Double、Character、Boolean、int、byte、short、long、float、double、char、boolean)
				//解析屬性xml標籤,並將解析結果賦值到currentObj中
				
				String setMethod = "set" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
				Method method = c.getDeclaredMethod(setMethod, field.getType());
				Element fieldElement = element.element(field.getName().toUpperCase());
				if(fieldElement != null) 
				{
					String value = fieldElement.getText();
					Object fieldObj = basicType.getConstructor(String.class).newInstance(value);
					method.invoke(currentObj, fieldObj);
				}
				else
				{
					throw new Exception("parseXml Error. target:" + field.getName() + " is not exists");
				}
				
			}
			else
			{
				if (isCollection(field.getType()))
				{
					//Collection解析
					
					String getMethodStr = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
					String setMethodStr = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
					Method getMethod = c.getDeclaredMethod(getMethodStr);
					Collection collection = getCollectionByClass(field.getType());
					Method setMethod = c.getDeclaredMethod(setMethodStr, field.getType());
					setMethod.invoke(currentObj, collection);
					
					//正式返回類型的type對象。例如:java.util.List<com.bayern.xml.example.entity.req.StaffBindReqBody$Staffs>
					Type returnType = getMethod.getGenericReturnType();
					
					//ParameterizedType : Comparable<? super T> , Collection符合該類型格式,例如Collection<String>。
					if (returnType instanceof ParameterizedType)
					{
						ParameterizedType t = (ParameterizedType) returnType;
						
						//getActualTypeArguments():返回表示此類型實際類型參數的 Type 對象的數組。 
						//由於List、Set泛型中只有一個參數,因此直接經過[0]獲取。
						Type pType = t.getActualTypeArguments()[0];
						
						//Collection的泛型對象
						Class pc = Class.forName(((Class) pType).getName());
						
						Method addMethod = field.getType().getDeclaredMethod("add", Object.class);
						List<Element> elementList = element.elements(field.getName().toUpperCase());
						for(Element pcElement : elementList) {
							Object parameterObj = pc.newInstance();
							addMethod.invoke(collection, new Object[]{parameterObj});
							parseXml(pc, parameterObj, true, pcElement);
						}
						
					}
				}
				else
				{
					//對象解析
					parseXml(field.getType(), currentObj, false, currentElement);
				}
			}
		}

		return currentObj;
	}



bean ——>XML app

/**
	 * 封裝xml
	 * @param c 目標對象Class類
	 * @param currentObj 被轉換對象
	 * @param flag 是否須要xml頭及root標籤
	 * @return 解析後的xml
	 * @throws Exception
	 * @throws NoSuchMethodException
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String packageXml(Class c, Object currentObj, boolean flag) throws Exception 
	{
		if(currentObj == null) 
		{
			return "";
		}
		StringBuffer xml = new StringBuffer();
		if(flag) 
		{
			xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
			String[] strs = c.getName().split("\\.");
			xml.append("<").append(strs[strs.length-1].toUpperCase()).append(">");
		}
		Field[] fieldArray = c.getDeclaredFields();
		for(Field field : fieldArray) 
		{
			if(field.isAnnotationPresent(XmlTransformAnnotation.class))
			{
				XmlTransformAnnotation xmlAnnotation = field.getAnnotation(XmlTransformAnnotation.class);
				if(XmlTransformAnnotation.FLASE.equals(xmlAnnotation.value()))
				{
					continue;
				}
			}
			
			Class basicType = getBasicType(field.getType());
			if (basicType != null)
			{
				//分裝基本類型(包括:String、Integer、Byte、Short、Long、Float、Double、Character、Boolean、int、byte、short、long、float、double、char、boolean)
				
				xml.append("<").append(field.getName().toUpperCase()).append(">");
				String setMethod = "get" + field.getName().substring(0,1).toUpperCase() + field.getName().substring(1);
				Method method = c.getDeclaredMethod(setMethod);
				String value = method.invoke(currentObj) != null ? method.invoke(currentObj).toString() : "";
				xml.append(value);
				xml.append("</").append(field.getName().toUpperCase()).append(">");
			}
			else
			{
				if (isCollection(field.getType()))
				{
					//分裝Collection
					
					String getMethod = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
					Method method = c.getDeclaredMethod(getMethod);
					Object collectionObj = method.invoke(currentObj);
					Type returnType = method.getGenericReturnType();
					if (returnType instanceof ParameterizedType)
					{
						ParameterizedType t = (ParameterizedType) returnType;
						Type pType = t.getActualTypeArguments()[0];
						Class pc = Class.forName(((Class) pType).getName());
						
						Collection collection = (Collection)collectionObj;
						if(collection != null) 
						{
							for(Iterator iter = collection.iterator(); iter.hasNext();)
							{
								Object subObj = iter.next();
								xml.append("<").append(field.getName().toUpperCase()).append(">");
								String subXml = packageXml(pc, subObj, false);
								xml.append(subXml);
								xml.append("</").append(field.getName().toUpperCase()).append(">");
							}
						}
							
					}
				}
				else
				{
					//分裝對象
					
					String[] strs = field.getName().split("\\.");
					strs = strs[strs.length - 1].split("\\$");
					String className = strs[strs.length - 1];
					xml.append("<").append(className.toUpperCase()).append(">");
					String getMethod = "get" + className.substring(0, 1).toUpperCase() + className.substring(1);
					Method method = c.getDeclaredMethod(getMethod);
					Object subObj = method.invoke(currentObj);
					String subXml = packageXml(field.getType(), subObj, false);
					xml.append(subXml);
					xml.append("</").append(className.toUpperCase()).append(">");
				}
			}
		
			
		}
		if(flag) 
		{
			String[] strs = c.getName().split("\\.");
			xml.append("</").append(strs[strs.length-1].toUpperCase()).append(">");
		}
		return xml.toString();
	}


輔助方法 spa

/**
	 * 判斷Class的類型是否是基本類型。基本類型包括:String、Integer、Byte、Short、Long、Float、Double、Character、Boolean、int、byte、short、long、float、double、char、boolean
	 * 若是是基本類型則返回對應的Class,不然返回null
	 * @param type
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	private static Class getBasicType(Class type) 
	{
		if (String.class.equals(type))
		{
			return String.class;
		}
		else if (Integer.class.equals(type))
		{
			return Integer.class;
		}
		else if (Byte.class.equals(type))
		{
			return Byte.class;
		}
		else if (Short.class.equals(type))
		{
			return Short.class;
		}
		else if (Long.class.equals(type))
		{
			return Long.class;
		}
		else if (Float.class.equals(type))
		{
			return Float.class;
		}
		else if (Double.class.equals(type))
		{
			return Double.class;
		}
		else if (Character.class.equals(type))
		{
			return Character.class;
		}
		else if (Boolean.class.equals(type))
		{
			return Boolean.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_BOOLEAN))
		{
			return Boolean.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_BYTE))
		{
			return Byte.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_CHAR))
		{
			return Character.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_DOUBLE))
		{
			return Double.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_FLOAT))
		{
			return Float.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_INT))
		{
			return Integer.class;
		}
		else if(type.getName().equals(Constant.BASIC_TYPE_SHORT))
		{
			return Short.class;
		}
		return null;
	}
	
	/**
	 * 判斷Class是否是Collection類型,這裏之判斷了List、Set兩種
	 * @param type
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	private static boolean isCollection(Class type) throws Exception
	{
		//isAssignableFrom(Class<?> cls)斷定此 Class 對象所表示的類或接口與指定的 Class 參數所表示的類或接口是否相同,或是不是其超類或超接口。
		if(List.class.isAssignableFrom(type)) {
			return true;
		} else if(Set.class.isAssignableFrom(type)) {
			return true;
		}
		return false;
	}
	
	/**
	 * 根據class獲取Collection
	 * @param type Collection對應的Class
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	private static Collection getCollectionByClass(Class type) throws Exception 
	{
		Collection collection = null;
		if(type.isInterface()) {
			List list = new ArrayList();
			Set set = new HashSet();
			
			//isInstance(Object obj)斷定指定的 Object 是否與此 Class 所表示的對象賦值兼容。
			if (type.isInstance(list))
			{
				collection = list;
			}
			else if(type.isInstance(set))
			{
				collection = set;
			}
		}else {
			collection = (Collection)type.newInstance();
		}
		
		return collection;
	}


完整代碼連接:https://git.oschina.net/bayern.com/XmlTransformFrame.git .net

相關文章
相關標籤/搜索