springboot集成jackson-dataformat-xml实现发送XML请求和XML响应参数处理

背景

最近在做发票相关的业务,需要对接第三方进行开发票等一系列操作,对方的系统是较老系统,需要采用XML的请求方式。

思路

一般来说,基于springboot的项目采用的都是JSON格式的请求参数和响应参数,因此需要做一个转换。
从格式上,XML格式的数据,是一个XML头后面是各种标签存放数据。例如data标签代表数据,orderno标签代表订单编号字段。

<?xml version="1.0" encoding="utf-8"?>
<data>
	<orderno>123456789</orderno>
	<ordertype>2</ordertype>
	<ticketno>666555</ticketno>
</data>

手动拼接

这是最容易想到的方式,因为格式相对固定,字段不多的请求下直接手动拼接就好了。

jackson框架

jackson-dataformat-xml框架提供了bean转xml和xml转bean的能力,并且使用简单,省去了繁琐的拼接操作。

springboot集成jackson-dataformat-xml

1.引入依赖

需要注意,如果项目已经引入过jackson依赖,在引入jackson-dataformat-xml依赖的时候需要保持依赖版本一致,可以通过在依赖管理搜jackson来查看版本。如果版本一致还是报错,考虑使用更高版本。

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.11.3</version>
        </dependency>

2.添加注解

如下:(设置标签名都是设置localName字段)
@JacksonXmlRootElement注解用来生成参数外一层的标签,也就是data标签,只有当对象是根对象的时候才生效,也就是最外层对象,如果作为某个对象的属性,则不生效。
@JacksonXmlProperty注解用来生成具体参数的标签,如payorderno字段,会根据注解配置生成ticketno标签,如果标签名和字段名一致可省略。如下,orderno、ordertype都因为字段名和标签名一致可省略该注解。
注意:如果标签名首字母是大写的,在定义字段的时候就必须用@JacksonXmlProperty注解指定。

如果内部是其他对象的引用,也把它当成一个字段即可,通过加@JacksonXmlProperty注解来设置对象引用的标签名。
如果内部是一个list,则需要加@JacksonXmlElementWrapper注解,来设置list标签的名称。@JacksonXmlProperty来设置list内部对象的标签。

//内部对象,本例子中insideData不生效
@Data
@JacksonXmlRootElement(localName = "insideData")
public class InsideBO {
	private String level;
}

//list存的对象,listData也不生效
@Data
@JacksonXmlRootElement(localName = "listData")
public class ListBO {
	private String name;

	private Integer age;
}

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;
import java.util.List;
@Data
@JacksonXmlRootElement(localName = "data")
@JsonIgnoreProperties(ignoreUnknown = true)
public class TestBO {
	private String orderno;

	private Integer ordertype;

	@JacksonXmlProperty(localName = "ticketno")
	private String payorderno;
	/**
	 * 指定该对象引用的标签为testInsideBO3,把它也当成普通字段即可
	 */
	private InsideBO testInsideBO1;

	@JacksonXmlProperty(localName = "testInsideBO3")
	private InsideBO testInsideBO2;
	/**
	 * 不指定list和内部对象的标签,默认都使用字段名
	 */
	private List<ListBO> listBOS1;
	/**
	 * 指定list的标签为listBOS3,内部对象的标签为listdetail
	 */
	@JacksonXmlElementWrapper(localName = "listBOS3")
	@JacksonXmlProperty(localName = "listdetail")
	private List<ListBO> listBOS2;

}

3.转换

bean转xml


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;

@SpringBootTest
public class Test {
	@org.junit.jupiter.api.Test
	public void test(){
		TestBO testBO=new TestBO();
		testBO.setOrderno("123456789");
		testBO.setOrdertype(2);
		testBO.setPayorderno("666555");

		List<ListBO> list=new ArrayList<>();
		ListBO listBO=new ListBO();
		listBO.setName("list");
		listBO.setAge(18);
		list.add(listBO);
		testBO.setListBOS1(list);
		testBO.setListBOS2(list);

		InsideBO insideBO=new InsideBO();
		insideBO.setLevel("100");
		testBO.setTestInsideBO1(insideBO);
		testBO.setTestInsideBO2(insideBO);

		XmlMapper xmlMapper=new XmlMapper();
		String s1 = null;
		try {
			s1 = xmlMapper.writeValueAsString(testBO);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		System.out.println(s1);
	}
}

打印结果如下:

<data>
<orderno>123456789</orderno>
<ordertype>2</ordertype>
<ticketno>666555</ticketno>
<testInsideBO1>
	<level>100</level>
</testInsideBO1>
<testInsideBO3>
	<level>100</level>
</testInsideBO3>
<listBOS1>
	<listBOS1>
		<name>list</name>
		<age>18</age>
	</listBOS1>
</listBOS1>

<listBOS3>
	<listdetail>
		<name>list</name>
		<age>18</age>
	/listdetail>
</listBOS3>
</data>

只需要再拼接一个xml的头就可以用来发请求了。

xml转bean

以上面转换得到的xml结果作为本次转换的入参。加上xml头更符合响应的xml

注意:默认情况下,如果XML返回的字段在实体类里面找不到,就会抛异常,需要在实体添加注解来忽略未知的字段。
@JsonIgnoreProperties(ignoreUnknown = true)

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;

@SpringBootTest
public class Test {
	@org.junit.jupiter.api.Test
	public void test(){
		TestBO testBO=new TestBO();
		testBO.setOrderno("123456789");
		testBO.setOrdertype(2);
		testBO.setPayorderno("666555");

		List<ListBO> list=new ArrayList<>();
		ListBO listBO=new ListBO();
		listBO.setName("list");
		listBO.setAge(18);
		list.add(listBO);
		testBO.setListBOS1(list);
		testBO.setListBOS2(list);

		InsideBO insideBO=new InsideBO();
		insideBO.setLevel("100");
		testBO.setTestInsideBO1(insideBO);
		testBO.setTestInsideBO2(insideBO);

		XmlMapper xmlMapper=new XmlMapper();
		String s1 = null;
		try {
			s1 = xmlMapper.writeValueAsString(testBO);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		System.out.println(s1);
		s1="<?xml version=\"1.0\" encoding=\"gb2312\"?>"+s1;
		System.out.println(s1);
		TestBO testBO1 = null;
		try {
			testBO1 = xmlMapper.readValue(s1, TestBO.class);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		System.out.println(testBO1);
	}
}

打印结果如下:
成功将xml参数转换成bean.

TestBO(orderno=123456789,
 	ordertype=2, 
 	payorderno=666555,
	testInsideBO1=InsideBO(level=100),
 	testInsideBO2=InsideBO(level=100),
 	listBOS1=[ListBO(name=list, age=18)],
    listBOS2=[ListBO(name=list, age=18)]
    )
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值