自实现 XML 与 对象 间的自动转换
来源:互联网 发布:史丹利快报的淘宝店 编辑:程序博客网 时间:2024/04/18 05:05
在java中,解析、分装xml是一件非常“麻烦”的事。我们常常需要写大量的代理来解析不同的XML文件,然后将解析结果赋值给相关对象,便于更好的使用;或者将相关对象转换成XML格式进行输出。为了减去这繁琐的操作,笔者通过反射、注解的功能来实现 XML 与 JAVA对象 的相互转换。
同时,可能存在协议的变动,某些xml标签可能不在返回,这里也提供通过注解,快速屏蔽bean中某些属性的解析和分装。大大提高了转换的灵活度,以及便于最小程度的改动现有代码。
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){//若属性标示为无需解析,则continueif(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
/** * 封装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())){//分装CollectionString 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();}
辅助方法
/** * 判断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
0 0
- 自实现 XML 与 对象 间的自动转换
- 使用XStream注解实现Java对象与XML互相转换的代码示例---转自:http://www.blogjava.net/bolo
- xml与对象的转换
- 实现Python对象与xml之间的相互转换
- Jaxb实现Java对象与XML之间的转换
- 使用 XStream 实现 Java 对象与 XML 的相互转换
- JAXB 可以实现Java对象与XML的相互转换
- [XML]castor: java对象与xml间的转换
- 对象与XML之间的转换
- java对象与xml的转换
- xml与java对象的相互转换
- Java对象与XML的相互转换
- xml与Java对象的转换
- xml-xml与java对象之间的转换(jaxb)
- JAXB 实现java对象与xml之间互相转换(一)
- JAXB 实现java对象与xml之间互相转换(二)
- JAXB 实现java对象与xml之间互相转换
- JAXB 实现java对象与xml之间互相转换
- debuginfo-install glibc-2.12-1.166.el6_7.3.x86_64类似的问题
- 记录 Linux环境下 web项目CPU爆表 “事故”,肇事者:GC
- 转载的另一篇不错的介绍gdb的文章
- spring实战第三版自学---第一章
- C语言———strtol()详解
- 自实现 XML 与 对象 间的自动转换
- 前端八个常见错误
- CentOS7搭建lamp
- 欢迎使用CSDN-markdown编辑器
- 5 异常、finally、权限、jar包、模板模式
- 关于游戏程序员的职业规划
- HDU-1005 Number Sequence && 51NOD-1126 求递推序列的第N项
- Java基础之-----集合框架
- Socket网络编程详解