这几天在做微信公众号
做的过程中想找个java bean转xml的工具,找了几个用着不知道是配置不好还是怎么回事,都会有一些问题,
然后脑子一热谢了一个javabean和xml的转换的工具里,自己用着还行,虽然有一些约束吧 ,
还是贴出来记录一下
顺便你提一下下,这个转换工具支持属性为集合、数组和非基本属性的对象。
package com.uke.util;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.xml.sax.InputSource;
import com.uke.bean.Message;
import com.uke.bean.remsg.Music;
import com.uke.bean.remsg.ReMusicMsg;
/**
*
* @author q821424508@sina.com
*
*/
public class BeanUtil {
/**
* 对象转为xml字符串
* @param obj
* 需要转xml的对象
* @param root
* xml跟标签的名称,默认为xml
* @return
* 返回转换后的xml
* <br>
* 说明:
* <br>
* 目前来说这个方法能够把对象转换成xml字符串没有什么问题,但是对bean类有一定的要求:
* <br>
* 1.<strong>bean类的没有需要设置的属性必须有getter、setter方法</strong>
* 2.<strong>生成的xml不会设置到xml的属性</strong>
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
* @throws JDOMException
* @throws IOException
* @throws ParserConfigurationException
*/
public static String convertToXml(Object obj,String root) throws InstantiationException {
//加这一句判断是为了方便递归调用,如果root为空,那么视为第一次调用,也就是xml的根
if(StrUtil.isNullOrEmptyOrBlank(root)){
root = "xml";
}
if(root.equalsIgnoreCase("item")){
、!!为什么只有这个以的item的i是小写的,其他的标签都是第一个字符大写的。why
root = root.toLowerCase();
}
try {
//声明一个列表 存放需要转换成xml类的所有设计的父类
//这个地方没有涉及到属性为类的地方,应为下面的处理方法是,如果属性是类的话,就递归调用这个方法,所以没有什么需要担心的
List<Class<?>> cl = new ArrayList<Class<?>>();
//获取对象的类
Class<?> clazz = obj.getClass();
//判断,如果父类不是Object的话把所有的类放到上面声明的list里面
String simpleName = clazz.getSimpleName();
while (!"Object".equals(simpleName)) {
cl.add(clazz);
clazz = clazz.getSuperclass();
simpleName = clazz.getSimpleName();
}
//上面是从子类开始存放的,所以这里要反转
Collections.reverse(cl);
//开始创建xml
StringBuffer xml = new StringBuffer("<"+root+">\n");
for (Class<?> cz : cl) {
//System.out.println("list " + cz.getName());
//获取类里面声明的所有属性,之所以上面要获取父级的类,时应为这里只能获取当前类的声明方法,无法获取到集成来的方法
Field[] fs = cz.getDeclaredFields();
for (Field f : fs) {
// System.out.println("f.getName() = "+f.getName());
// System.out.println("f.getName() = "+f.getType().getName());
//
//获取属性的类型
Class<?> ct =f.getType();
//获取类对应的名称
String ctName = ct.getSimpleName();
String fName = f.getName();
String firstUpperName = fName.substring(0, 1).toUpperCase()+fName.substring(1);
//System.out.println();
//当然,如果类是基础类型的直接设值就可以了
if("int".equals(ctName) || "long".equals(ctName)|| "double".equals(ctName)|| "float".equals(ctName) || "char".equals(ctName)){
xml.append(getFieldXml(f,cz,obj)).append("\n");
}else if("String".equals(ctName)||"char".equals(ctName)){
xml.append(getFieldXml(f,cz,obj)).append("\n");
}else {
//如果属性不是基础类型的,则需要递归调用,也就是把上面的方法冲走一遍
//通过执行get方法,获取对象的返回值。
String methodName = "get" +firstUpperName;
Class<?>[] cnull = null;
Method m=cz.getMethod(methodName, cnull);
Object[] osnull =null;
Object reto=m.invoke(obj, osnull);
if(null!=reto){
if(reto instanceof Collection<?>){
//如果结果是集合类型,那么获取子元素继续
xml.append("<"+firstUpperName+">\n");
Collection<Object> ol = (Collection<Object>)reto;
for(Object o:ol){
xml.append(convertToXml(o,o.getClass().getSimpleName()));
}
xml.append("</"+firstUpperName+">\n");
}else if(reto instanceof Array){
//如果结果是数组类型,那么获取数组里每个元素继续
xml.append("<"+firstUpperName+">\n");
Object[] ol = (Object[])reto;
for(Object o:ol){
xml.append(convertToXml(o,o.getClass().getSimpleName()));
}
xml.append("</"+firstUpperName+">\n");
} else{
//如果返回值不为null 执行递归调用
xml.append(convertToXml(reto,ctName));
}
}else{
//如果为null,直接在这个属性里面设置为空就可以了
xml.append("<"+firstUpperName+">\n</"+firstUpperName+">\n");
}
}
}
}
xml.append("</"+root+">\n");
return xml.toString();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* 通过Filed,Class,和Objec对象获取需要生成的对应Filed的字符串
* @param f
* @param cz
* @param obj
* @return
* @throws NoSuchMethodException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws InvocationTargetException
*/
private static String getFieldXml(Field f, Class<?> cz, Object obj) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
String fName = f.getName();
String firstUpperName = fName.substring(0, 1).toUpperCase()+fName.substring(1);
String str = "<"+firstUpperName+">";
String methodName = "get" +firstUpperName;
Class<?>[] cnull = null;
Method m=cz.getMethod(methodName, cnull);
Object[] osnull =null;
Object reto=m.invoke(obj, osnull);
if(null!=reto){
Class<?> ct =f.getType();
String ctName = ct.getSimpleName();
if("int".equals(ctName) || "long".equals(ctName)){
if("0".equals(reto.toString())){
System.err.println(fName +" 对应的值为0");
}
str +=reto.toString();
}else if("double".equals(ctName)|| "float".equals(ctName)){
if("0.0".equals(reto.toString())||"0".equals(reto.toString())){
System.err.println(fName +" 对应的值为0");
}
str +=reto.toString();
}else{
str +="<![CDATA["+reto.toString()+"]]>";
}
}else{
System.err.println(fName +" 对应的值为空");
}
str +="</"+firstUpperName+">";
return str;
}
/**
* 通过xml字符串转换成给定类的对象
* @param xml
* 需要转成对象的字符串
* @param c
* 返回对象的类[Class]
* @return
* 返回对象的实例
* <br>
* 1.转换过程中不会操作任何xml的属性操作,值是一个标签对应一个属性来操作的
* <br>
* 2.参数Class<?> c对应的类,需要设置的属性都必须有getter,setter方法
*/
public static <T> T converyToJavaBean(String xml, Class<T> c) {
T t = null;
try {
t= c.newInstance();
SAXBuilder sb = new SAXBuilder();
StringReader read = new StringReader(xml);
InputSource source = new InputSource(read);
Document doc = sb.build(source);
Element root =doc.getRootElement();
convery(root,c,t);
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
private static void convery(Element e,Class<?> clazz,Object o) throws SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException{
// System.out.println("el.size = "+el.size());
// String text = e.getTextTrim();
// System.out.println("text = "+text);
String en =e.getName();
if("xml".equals(en)){
List<Element> el = e.getChildren();
for(Element e1:el){
convery(e1,clazz,o);
}
}else{
List<Element> el = e.getChildren();
if(el.size()>0){
String childClassName =e.getName();
String methodName = "get" +childClassName.substring(0, 1).toUpperCase()+childClassName.substring(1);
Class<?> clazz1 = null;
Method[] ms = clazz.getMethods();
for(Method m:ms){
// System.out.println(m.getName());
if(methodName.equals(m.getName())){
clazz1 = m.getReturnType();
}
}
// try {
// clazz1 = Class.forName(ncn);
// } catch (Exception e2) {
// System.err.println(ncn + " 实例化失败,请检查是否存在这个类 ");
// }
if(null==clazz1){
//没有找到对应的类,这里只是忽略
System.out.println(methodName + " 方法未找到,或者返回类型不正确 ");
return;
}
Object o1 = clazz1.newInstance();
try {
//反射获取set方法,帮o1的值设置进o里面
Method m =clazz.getMethod(methodName, clazz1);
m.invoke(o, o1);
} catch (Exception e2) {
//应该是没有找到对应的方法,忽略
System.err.println(methodName +" 方法调用失败,请检查方法是否存在");
return ;
}
for(Element e1:el){
convery(e1,clazz1,o1);
}
}else{
String eName = e.getName();
String methodName = "set" +eName.substring(0, 1).toUpperCase()+eName.substring(1);
Method[] ms=clazz.getMethods();
for(Method m:ms){
if(m.getName().equals(methodName)){
Class<?>[] c= m.getParameterTypes();
//目前只支持带一个参数的情况
String text = e.getTextTrim();
Object v = null;
String cn = c[0].getSimpleName();
if("int".equals(cn)){
v = Integer.parseInt(text);
}else if("long".equals(cn)){
v= Long.parseLong(text);
}else if("double".equals(cn)){
v = Double.parseDouble(text);
}else if("float".equals(cn)){
v = Float.parseFloat(text);
}else{
v = text;
}
m.invoke(o,v);
}
}
}
}
}
public static void main(String[] args) throws NoSuchMethodException,
SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, JDOMException,
IOException, ParserConfigurationException, InstantiationException {
ReMusicMsg rmm = new ReMusicMsg();
Music m = new Music();
m.setTitle("小苹果");
m.setDescription("小苹果");
m.setMusicUrl("http://yinyueshiting.baidu.com/data2/music/122112390/12012502946800128.mp3?xcode=b7d19aa0a1f43850273d9292ca2357ec3f8882ee658cd7de");
m.setHQMusicUrl("http://yinyueshiting.baidu.com/data2/music/122112390/12012502946800128.mp3?xcode=b7d19aa0a1f43850273d9292ca2357ec3f8882ee658cd7de");
rmm.setMusic(m);
rmm.setMsgType("music");
rmm.setCreateTime((int)(System.currentTimeMillis()/1000));
rmm.setFromUserName("gh_32a91b043d76");
rmm.setToUserName("os6Z4swOSB6pzVDtA90g0Fq4Dz_4");
rmm.setFuncFlag(1);
rmm.setMsgId(6051426418514665443l);
rmm.setMsgType("music");
String xml =convertToXml(rmm,null);
System.out.println(xml);
xml = "<xml><ToUserName><![CDATA[gh_32a91b043d76]]></ToUserName>/n<FromUserName><![CDATA[os6Z4swOSB6pzVDtA90g0Fq4Dz_4]]></FromUserName>/n<CreateTime>1409041861</CreateTime>/n<MsgType><![CDATA[text]]></MsgType>/n<Content><![CDATA[哈哈]]></Content>/n<MsgId>6051788711890992105</MsgId>/n</xml>/n";
xml =xml.replaceAll(">/n", ">");
System.out.println(xml);
Message ms = converyToJavaBean(xml, Message.class);
System.out.println(ms.getMsgType());
}
}
使用和约束什么的,在方法头部已经写出来了,这里就不多说了,
如果你想测试的话,可能需要一下jar和一些自定义的类,
自定义的类你可以更具用到的属性直接写一个就行了,就是简单的属性和getter setter方法
jar包应该只要jdom的就可以了
已添加附件