如何实现JAVABean和XML的相互转化

声明:此文为原创,转载请声明出处!

最近在项目中用到了JAVABean和XML的相互转化,由于花了比较多的时间和精力去实现,所以记录一下是如何实现的。我用到的JAVABean转xml有两种实现办法,第一种是利用工具类直接转化,第二种是先将JAVABean转换成JSON,然后再转成XML。我的项目是用springboot搭建的,jdk是1.8的, maven版本是3.6.0。

第一种:利用工具类将JAVABean直接转成XML

首先创建一个工具类,类里面有两种方法,xml转JAVABean和JAVABean转xml,网上工具类有很多,这个大家自己选择,有这两种方法就可以。

 /**
     * 将对象转为对应的xml报文
     *
     * @param object 对象
     * @param classT 类
     * @return xml
     * @throws JAXBException ex
     */
    public static String objectToXml(Object object, Class<?>... classT) throws JAXBException {
        StringWriter writer = new StringWriter();
        JAXBContext context = JAXBContext.newInstance(classT);
        Marshaller marshaller = context.createMarshaller();
        //设置编码格式
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
        marshaller.marshal(object, writer);
        return new String(writer.getBuffer());
    }

    /**
     * 将xml报文转换为对象
     *
     * @param clazz  clazz
     * @param xmlStr xml
     * @return object
     */
    public static Object xmlToObject(String xmlStr, Class<?>... clazz) {
        Object xmlObject = null;
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            StringReader sr = new StringReader(xmlStr);
            xmlObject = unmarshaller.unmarshal(sr);
        } catch (JAXBException e) {
            log.error("xmlStrToObject error:", e);
        }
        return xmlObject;
    }

这个工具类我引了一个lombok用来打印日志 不用的可以去掉

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

接下来再创建一个实体类

@XmlRootElement(name = "Student")
public class Student {

    @XmlElement(name = "Name")
    private String name;

    @XmlElement(name = "Sex")
    private String sex;

    @XmlTransient
    public String getName() { return name; }

    public void setName(String name) { this.name = name; }

    @XmlTransient
    public String getSex() { return sex; }

    public void setSex(String sex) { this.sex = sex; }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

其中主要起作用的是@XmlRootElement(name = "Student")@XmlElement(name = "Name")@XmlTransient这三个注解,其中@XmlRootElement(name = "Student")这个注解是必须要用的,用在类名上,name属性是用来设置xml根节点的名字,如果没有的话,就默认是全小写的类名。@XmlElement(name = "Name")@XmlTransient是搭配用的,要么都不用,要么都用,不能缺一个,不然使用工具类转化的时候会报错。
接下来创建一个测试方法

    public String jsonToXml() throws Exception{
        Student student = new Student();
        student.setName("张三");
        student.setSex("男");
        log.info("student:"+student.toString());
        String xml = XmlUtil.objectToXml(student,Student.class);
        log.info("xml:"+xml);
        return xml;
    }

XmlUtil.objectToXml(Object object, Class<?>… classT)这个方法,第一个参数是要转化的实体类,第二个参数是实体类的class数组
执行结果为:

student:Student{name='张三', sex='男'}
xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Student>
    <Name>张三</Name>
    <Sex>男</Sex>
</Student>

执行结果我格式化了一下 方便大家看。这样一个简单的JAVABean转xml就成功了,那项目实际会有更复杂的JAVABean,那再创建一个课程的实体类。

public class Course {

    @XmlElement(name = "Id")
    String id;

    @XmlElement(name = "Score")
    String score;

    @XmlTransient
    public String getId() { return id; }

    public void setId(String id) { this.id = id; }

    @XmlTransient
    public String getScore() { return score; }

    public void setScore(String score) { this.score = score; }

    @Override
    public String toString() {
        return "Course{" +
                "id='" + id + '\'' +
                ", score='" + score + '\'' +
                '}';
    }
}

然后把Course当做Student的一个属性,这时候Student就变成了下面这样:

@XmlRootElement(name = "Student")
public class Student {

    @XmlElement(name = "Name")
    private String name;

    @XmlElement(name = "Sex")
    private String sex;

    @XmlElement(name = "Course")
    private Course course ;

    @XmlTransient
    public String getName() { return name; }

    public void setName(String name) { this.name = name; }

    @XmlTransient
    public String getSex() { return sex; }

    public void setSex(String sex) { this.sex = sex; }

    @XmlTransient
    public Course getCourse() { return course; }

    public void setCourse(Course course) { this.course = course; }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", course=" + course.toString() +
                '}';
    }
}
测试类变成了下面这样:
    public String jsonToXml() throws Exception{
        Student student = new Student();
        student.setName("张三");
        student.setSex("男");
        Course course = new Course();
        course.setId("01");
        course.setScore("100");
        student.setCourse(course);
        log.info("student:"+student.toString());
        String xml = XmlUtil.objectToXml(student,Student.class);
        log.info("xml:"+xml);
        return xml;
    }
执行结果如下:
student:Student{name='张三', sex='男', course=Course{id='01', score='100'}}
xml:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Student>
    <Name>张三</Name>
    <Sex>男</Sex>
    <Course>
        <Id>01</Id>
        <Score>100</Score>
    </Course>
</Student>

有细心的同学可能发现了,Course这个类的类名上面没有@XmlRootElement注解,但是还可以正常运行。这是因为当一个类作为另一个类的属性转XML时,就不需要@XmlRootElement注解了,就算用了也不会生效,比如设置注解@XmlRootElement(name = "Course"),但是转化后的XML节点名字还是course。这种情况生效的是Student类中course属性上面的@XmlElement(name = "Course")注解了。
接下来用刚才转化后的XML来转回成JAVABean,测试代码如下:

    public Student xmlToJson() throws Exception{
        String xml  = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                "<Student>\n" +
                "    <Name>张三</Name>\n" +
                "    <Sex>男</Sex>\n" +
                "    <Course>\n" +
                "        <Id>01</Id>\n" +
                "        <Score>100</Score>\n" +
                "    </Course>\n" +
                "</Student>";
        log.info("xml:"+xml);
        Student student = (Student)XmlUtil.xmlToObject(xml,Student.class);
        log.info("student:"+student.toString());
        return student;
    }

执行结果如下:

xml:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Student>
    <Name>张三</Name>
    <Sex>男</Sex>
    <Course>
        <Id>01</Id>
        <Score>100</Score>
    </Course>
</Student>
student:Student{name='张三', sex='男', course=Course{id='01', score='100'}}

这样一个简单的XML和JAVABean的相互转化就完成了。
那还有一种稍微复杂的情况就是,现在有一个MathCourse类,继承了Course类,然后作为Student的course属性,这样的话,之前的方法就不适用了。先来看看MathCourse类长什么样:

@XmlRootElement(name = "MathCourse")
public class MathCourse extends Course{
    @XmlElement(name = "TeacherId")
    private String teacherId;

    @XmlTransient
    public String getTeacherId() { return teacherId; }

    public void setTeacherId(String teacherId) { this.teacherId = teacherId; }
}

改完后的Student类:

@XmlRootElement(name = "Student")
public class Student {

    @XmlElement(name = "Name")
    private String name;

    @XmlElement(name = "Sex")
    private String sex;


    private Course course ;

    @XmlTransient
    public String getName() { return name; }

    public void setName(String name) { this.name = name; }

    @XmlTransient
    public String getSex() { return sex; }

    public void setSex(String sex) { this.sex = sex; }

    @XmlElementRef
    public Course getCourse() { return course; }

    public void setCourse(Course course) { this.course = course; }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", course=" + course.toString() +
                '}';
    }
}

这个时候Student类就不能用@XmlElement(name = "Name")@XmlTransient这一对注解了,要用@XmlElementRef这个注解,如果不用注解或者还是用@XmlElement(name = "Name")这一对注解的话,也不会报错,但是<course>会变成<course xsi:type=“mathCourse” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”>,所以改成@XmlElementRef注解就正常了,有兴趣的同学可以去查查为什么。还有一点要注意的就是MathCourse类上面的@XmlRootElement(name = "MathCourse")是有用的,测试类如下:

public String jsonToXml() throws Exception{
        Student student = new Student();
        student.setName("张三");
        student.setSex("男");
        MathCourse mathCourse = new MathCourse();
        mathCourse.setTeacherId("123");
        mathCourse.setId("02");
        mathCourse.setScore("99");
        student.setCourse(mathCourse);
        //course的实际子类类名要作为参数传给方法
        String xml = XmlUtil.objectToXml(student,Student.class,MathCourse.class);
        log.info("xml:"+xml);
        return xml;
    }

执行结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Student>
    <Name>张三</Name>
    <Sex>男</Sex>
    <MathCourse>
        <Id>02</Id>
        <Score>99</Score>
        <TeacherId>123</TeacherId>
    </MathCourse>
</Student>

这里要注意的是XmlUtil.objectToXml(student,Student.class,MathCourse.class)这个方法的MathCourse.class是一定要传的,不然会默认用Course类转化,这样就只有Course类的属性能转成xml,子类如MathCourse中的属性会丢失。
那用上面的执行结果来转回JAVABean,测试类如下:

    public String jsonToXml() throws Exception{
        String xml  = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                "<Student>\n" +
                "    <Name>张三</Name>\n" +
                "    <Sex>男</Sex>\n" +
                "    <MathCourse>\n" +
                "        <Id>02</Id>\n" +
                "        <Score>99</Score>\n" +
                "        <TeacherId>123</TeacherId>\n" +
                "    </MathCourse>\n" +
                "</Student>";
        Student student = (Student)XmlUtil.xmlToObject(xml,Student.class,MathCourse.class);
        MathCourse mathCourse = (MathCourse)student.getCourse();
        log.info("mathCourse:"+mathCourse.toString());
        return xml;
    }

执行结果如下:

mathCourse:MathCourse{teacherId='123', id='02', score='99'}

第二种:将JAVABean转成JSON后再转成XML

这个方法需要的依赖如下:

		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<classifier>jdk15</classifier>
		</dependency>
		<dependency>
			<groupId>xom</groupId>
			<artifactId>xom</artifactId>
			<version>1.2.5</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.dataformat</groupId>
			<artifactId>jackson-dataformat-xml</artifactId>
			<version>2.10.1</version>
		</dependency>
		<dependency>
            <groupId>de.odysseus.staxon</groupId>
            <artifactId>staxon</artifactId>
            <version>1.3</version>
        </dependency>

需要的工具类方法如下:

public String xml2json(String xml) {
        //创建XMLSerializer对象
        XMLSerializer xmlSerializer = new XMLSerializer();
        //将xml转化为json
        String result = xmlSerializer.read(xml).toString();
        return result;
    }

    public  String json2xml(String json) {
        StringReader input = new StringReader(json);
        StringWriter output = new StringWriter();
        JsonXMLConfig config = new JsonXMLConfigBuilder().multiplePI(false).repairingNamespaces(false).build();
        try {
            XMLEventReader reader = new JsonXMLInputFactory(config).createXMLEventReader(input);
            XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(output);
            writer = new PrettyXMLEventWriter(writer);
            writer.add(reader);
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                output.close();
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return output.toString();
    }

测试方法如下:

 public String jsonToXml() throws Exception{
        Student student = new Student();
        student.setName("张三");
        student.setSex("男");
        MathCourse mathCourse = new MathCourse();
        mathCourse.setTeacherId("123");
        mathCourse.setId("02");
        mathCourse.setScore("99");
        student.setCourse(mathCourse);
        //json转xml要有一个根节点
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("content",student);
        String xml = aopUtil.json2xml(jsonObject.toJSONString());
        log.info("xml:"+xml);
    }

转化结果如下:

xml:<?xml version='1.0'?>
<content>
	<course>
		<id>02</id>
		<score>99</score>
		<teacherId>123</teacherId>
	</course>
	<name>张三</name>
	<sex>男</sex>
</content>

用这个方法转成xml比较简单,需要注意的有两点,第一个就是一定要把JAVABean放到一个JSONObject里,有一个根节点,不然转化就会报错。第二个是转化的xml的节点名称就不受属性上面的@XmlElement()注解影响了,就像上面的转化结果一样,Student类的name注解是@XmlElement(name = "Name"),但是转化后节点名还是name。这个时候如果要改节点名的话,就要在属性上加上@JSONField()属性,现在改一下Student类的name如下:

    @XmlElement(name = "Name")
    @JSONField(name = "NameJSON")
    private String name;

转化的结果如下:

xml:<?xml version='1.0'?>
<content>
	<NameJSON>张三</NameJSON>
	<course>
		<id>02</id>
		<score>99</score>
		<teacherId>123</teacherId>
	</course>
	<sex>男</sex>
</content>

这样改节点名就成功了,@JSONField()属性用到的依赖如下

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.31</version>
		</dependency>

现在来把xml转为JSONObject,就用上面的结果来转,测试方法如下:

 Student student = new Student();
        student.setName("张三");
        student.setSex("男");
        MathCourse mathCourse = new MathCourse();
        mathCourse.setTeacherId("123");
        mathCourse.setId("02");
        mathCourse.setScore("99");
        student.setCourse(mathCourse);
        //json转xml要有一个根节点
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("content",student);
        String xml = aopUtil.json2xml(jsonObject.toJSONString());
        //log.info("student:"+student.toString());
        //String xml = XmlUtil.objectToXml(student,Student.class,MathCourse.class);
        log.info("xml:"+xml);
        String json = aopUtil.xml2json(xml);
        Student student1 = JSONObject.parseObject(json,Student.class);
        log.info("student:"+student1.toString());
        //不经过Student类直接取Course对象
        Course course = JSONObject.parseObject(json).getObject("course",Course.class);
        log.info("course:"+course.toString());

测试结果如下:

xml:<?xml version='1.0'?>
<content>
	<NameJSON>张三</NameJSON>
	<course>
		<id>02</id>
		<score>99</score>
		<teacherId>123</teacherId>
	</course>
	<sex>男</sex>
</content>
student:Student{name='张三', sex='男', course=Course{id='02', score='99'}}
course:Course{id='02', score='99'}

这样转化就成功了,要注意的是JAVAObject转xml时要有一个根节点,但是转回JAVAObject的时候,是没有这个节点的,可以直接用。还有一个比较方便的地方就是可以直接绕过Student类取到Course类,在某些场景下就比较好用了,比如一个节点比较多的xml,但是你只需要其中的一部分数据,那就可以直接取,不用再创建包装的类了。

参考:json转xml、xml转json

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值