Java中轻松搞XML和对象之间的互转,就它了!

谢谢平台提供-http://bjbsair.com/2020-04-13/tech-info/65241.html

前言

在微信订阅号和支付宝生活号日常开发中,我们会涉及到对象和XML之间的相互转换。

Java中轻松搞定XML和对象之间的互转,就它了!

比如我们可以利用StringBuilder去直接拼接来构造XML

    /**  
     * 构造基础的响应消息  
     *   
     * @return  
     */  
    public static String buildBaseAckMsg(String fromUserId) {  
        StringBuilder sb = new StringBuilder();  
        sb.append("<XML>");  
        sb.append("<ToUserId><![CDATA[" + fromUserId + "]]></ToUserId>");  
        sb.append("<AppId><![CDATA[" + AlipayServiceEnvConstants.APP_ID + "]]></AppId>");  
        sb.append("<CreateTime>" + Calendar.getInstance().getTimeInMillis() + "</CreateTime>");  
        sb.append("<MsgType><![CDATA[ack]]></MsgType>");  
        sb.append("</XML>");  
        return sb.toString();  
    }

作为像我这么懒得程序员,肯定会去找大佬写好的轮子,这就是我和XStream相遇的契机。下面我们一起走进XStream;

一.关于 XStream

Xstream 是一个简单的库,用于将对象序列化为 XML 然后再序列化回来。

二.简单入门

2.1 创建要序列化的类

这里有几个简单的类,XStream 可以将这些类的实例转换为 XML,然后再转换回来。

public class Person {  
  private String firstname;  
  private String lastname;  
  private PhoneNumber phone;  
  private PhoneNumber fax;  
  // ... constructors and methods  
}  
  
public class PhoneNumber {  
  private int code;  
  private String number;  
  // ... constructors and methods  
}

注意: 注意这些字段是私有的。Xstream 不关心字段的可见性。不需要getters or setters。此外,XStream 并不限制你拥有一个默认构造函数。

2.2 初始化 XStream

引入依赖

<dependency>  
    <groupId>com.thoughtworks.xstream</groupId>  
    <artifactId>xstream</artifactId>  
    <version>1.4.10</version>  
</dependency>

要使用 XStream,只需实例化 XStream 类:

XStream xstream = new XStream();

2.3.将序列化对象转为xml

让我们创建一个 Person 实例并填充它的字段:

        Person person = new Person("Joe", "milo");  
        person.setPhone(new PhoneNumber(123,"1234-456"));  
        person.setFax(new PhoneNumber(123,"999-456"));

现在,要将其转换为XML,只需要简单的调用XStream的toXML()方法

String xml = xstream.toXML(person);

Java中轻松搞定XML和对象之间的互转,就它了!

现在,为了使 XStream 输出的 XML 更简洁,可以为 XML 元素名的自定义类名创建别名。这是使用 XStream 所需的惟一映射类型,当然这是可选的。

xstream.alias("person",Person.class);

我们会发现XML变得更简洁

Java中轻松搞定XML和对象之间的互转,就它了!

2.4.将XML反序列化对象

首先,我们重写Person对象的toString()

    @Override  
    public String toString() {  
        return "Person{" +  
                "first + firstname + '\'' +  
                ", last + lastname + '\'' +  
                ", phone=" + phone +  
                ", fax=" + fax +  
                '}';  
    }

要重构一个对象,我们只需调用fromXML()方法

        XStream xstream = new XStream();  
        xstream.alias("person",Person.class);  
        //xml字符串  
        String xmldemo = "<?xml version=\"1.0\" ?><person><firstname>Joe</firstname><lastname>milo</lastname><phone><code>123</code><number>1234-456</number></phone><fax><code>123</code><number>999-456</number></fax></person>";  
        Person o = (Person)xstream.fromXML(xmldemo);  
        System.out.println(o.toString());

Java中轻松搞定XML和对象之间的互转,就它了!

关于更多关于Xstream的操作,大家可以阅读:

https://www.cnblogs.com/jpfss/p/9836465.html

三.高级入门

在高级入门中,我们以支付宝生活号开发为例,采用Xstream的注解开发来完成事件订阅过程中的xml报文相关的操作

3.1 项目搭建

首先我们搭建项目springboot-xstream,当然你可以在

https://gitee.com/milogenius/milogenius-springboot

找到源代码,案例位于springboot-xstream模块下面。由于案例代码太多,强烈建议大家下载源代码案例自己跑一跑。

Java中轻松搞定XML和对象之间的互转,就它了!

3.2 相关类解释

Java中轻松搞定XML和对象之间的互转,就它了!

3.3 和XStream相关的类

1.AlipayXmlMessage
package com.milo.xstream.xml;  
  
import com.thoughtworks.xstream.annotations.XStreamAlias;  
import com.thoughtworks.xstream.annotations.XStreamConverter;  
import lombok.Data;  
import lombok.extern.slf4j.Slf4j;  
  
import java.io.InputStream;  
import java.io.Serializable;  
import java.util.Map;  
  
/**  
 * 支付宝生活号推送过来的xml消息  
 * @author milogenius  
 * @date 2020/4/4 15:29  
 *  
 */  
@Data  
@Slf4j  
@XStreamAlias("XML")  
public class AlipayXmlMessage implements Serializable {  
  private static final long serialVersionUID = -3586245291677274914L;  
  
  /**  
   * 使用dom4j解析的存放所有xml属性和值的map.  
   */  
  private Map<String, Object> allFieldsMap;  
  
  ///  
  // 以下都是支付宝生活号推送过来的消息的xml的element所对应的属性  
  ///  
  
  /**AppId*/  
  //AppId--->xml中的字段  
  //appId --->pojo中的字段  
  @XStreamAlias("AppId")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  private String appId;  
  
  
  /**用户userid,用户唯一标识*/  
  @XStreamAlias("FromAlipayUserId")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  private String fromAlipayUserId;  
  
  
  /**消息创建时间*/  
  @XStreamAlias("CreateTime")  
  private Long createTime;  
  
  /**消息类型*/  
  @XStreamAlias("MsgType")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  private String msgType;  
  
  
  /**事件类型*/  
  @XStreamAlias("EventType")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  private String eventType;  
  
  /**用户从特定场景关注,带的自定义参数值*/  
  @XStreamAlias("ActionParam")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  private String actionParam;  
  
  /**支付宝用户信息*/  
  @XStreamAlias("UserInfo")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  private String userInfo;  
  
  /**消息id 用于消息去重*/  
  @XStreamAlias("MsgId")  
  private String msgId;  
  
  
  
  
  public static AlipayXmlMessage fromXml(String xml) {  
    //修改支付宝生活号变态的消息内容格式,方便解析  
    xml = xml.replace("<?xml version=\\\"1.0\\\" encoding=\\\"gbk\\\"?>", "");  
    final AlipayXmlMessage xmlMessage = XStreamTransformer.fromXml(AlipayXmlMessage.class, xml);  
    xmlMessage.setAllFieldsMap(XmlUtils.xml2Map(xml));  
    return xmlMessage;  
  }  
  
  public static AlipayXmlMessage fromXml(InputStream is) {  
    return XStreamTransformer.fromXml(AlipayXmlMessage.class, is);  
  }  
  
  
  
}

2.AlipayXmlOutMessage

package com.milo.xstream.outxml;  
  
import com.milo.xstream.builder.AckBuilder;  
import com.milo.xstream.xml.XStreamCDataConverter;  
import com.milo.xstream.xml.XStreamTransformer;  
import com.thoughtworks.xstream.annotations.XStreamAlias;  
import com.thoughtworks.xstream.annotations.XStreamConverter;  
import lombok.Data;  
  
import java.io.Serializable;  
  
/**  
 * 响应XML  
 * @author milogenius  
 * @date 2020/4/4 11:57  
 *  
 */  
@XStreamAlias("xml")  
@Data  
public abstract class AlipayXmlOutMessage implements Serializable {  
  private static final long serialVersionUID = -381382011286216263L;  
  
  /**接受者userid*/  
  @XStreamAlias("ToUserId")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  protected String toUserId;  
  
  /**支付宝生活号appid*/  
  @XStreamAlias("AppId")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  protected String appId;  
  
  /**创建时间*/  
  @XStreamAlias("CreateTime")  
  protected Long createTime;  
  
  /**消息类型*/  
  @XStreamAlias("MsgType")  
  @XStreamConverter(value = XStreamCDataConverter.class)  
  protected String msgType;  
  
  @XStreamAlias("response")  
  protected Response response;  
  
  @XStreamAlias("sign")  
  protected String sign;  
  
  @XStreamAlias("sign_type")  
  protected String signType;  
  
  /**  
   * 获得ack builder  
   * @return  
   */  
  public static AckBuilder ACK() {  
    return new AckBuilder();  
  }  
  
  
  
  @SuppressWarnings("unchecked")  
  public String toXml() {  
    StringBuilder builder = new StringBuilder();  
    String xml = XStreamTransformer.toXml((Class<AlipayXmlOutMessage>) this.getClass(), this);  
    builder.append("<?xml version=\"1.0\" encoding=\"gbk\"?>\n");  
    builder.append(xml);  
    return builder.toString();  
  }  
  
}

3.XStreamCDataConverter

package com.milo.xstream.xml;  
  
import com.thoughtworks.xstream.converters.basic.StringConverter;  
/**  
 * 自定义转换器  
 * @author milogenius  
 * @date 2020/4/4 10:56  
 *  
 */  
public class XStreamCDataConverter extends StringConverter {  
  
  @Override  
  public String toString(Object obj) {  
    return "<![CDATA[" + super.toString(obj) + "]]>";  
  }  
  
}

相关注解说明

@XStreamAlias用于定义XStream类或字段别名的注释

@XStreamConverter用于声明转换器的注释

3.4 测试

XmlDemoTest

package com.milo.xstream;  
  
import com.milo.xstream.outxml.AlipayXmlOutMessage;  
import com.milo.xstream.xml.AlipayXmlMessage;  
  
/**  
 * @author milogenius  
 * @date 2020-04-04 11:49  
 */  
public class XmlDemoTest {  
  
    public static void main(String[] args) {  
        //xml --->pojo  
        String bizContent = "<XML>\n" +  
                "    <AppId><![CDATA[2014070100171523]]></AppId>\n" +  
                "    <FromUserId><![CDATA[20882837462837462837462837461234]]></FromUserId>\n" +  
                "    <FromAlipayUserId><![CDATA[2088283746283746]]></FromAlipayUserId>\n" +  
                "    <CreateTime><![CDATA[1405943673657]]></CreateTime>\n" +  
                "    <MsgType><![CDATA[event]]></MsgType>\n" +  
                "    <EventType><![CDATA[follow]]></EventType>\n" +  
                "    <ActionParam><![CDATA[{\"scene\":{\"sceneId\": \"1234\"}}]]></ActionParam>\n" +  
                "    <AgreementId><![CDATA[]]></AgreementId>\n" +  
                "    <AccountNo><![CDATA[]]></AccountNo>\n" +  
                "    <UserInfo><![CDATA[{\"logon_id\":\"135****1009\",\"user_name\":\"*iuxu527\"}]]></UserInfo>\n" +  
                "</XML>";  
        AlipayXmlMessage alipayXmlMessage = AlipayXmlMessage.fromXml(bizContent);  
       // System.out.println(alipayXmlMessage);  
  
  
  
        //pojo --->xml  
        AlipayXmlOutMessage mpXmlOutMessage = AlipayXmlOutMessage.ACK().toUserId("123456").appId("99999999").build();  
        String xml = mpXmlOutMessage.toXml();  
        System.out.println(xml);  
  
    }  
}

3.5测试结果

3.5.1 xml ---->pojo

Java中轻松搞定XML和对象之间的互转,就它了!

3.5.2 pojo —>xml

Java中轻松搞定XML和对象之间的互转,就它了!

四.总结

通过上面的一些小案例,我们学习Xstream的基本用法和注解用法,文章到此为止,谢谢大家阅读;

Spring Boot提供了许多方式来实现XML和JSON之间转换。其一个常见的方式就是使用Jackson库。使用Jackson库可以很方便地将Java对象XML或JSON之间进行序列化和反序列化。 首先,我们需要在pom.xml文件添加以下依赖项: ``` <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.12.3</version> </dependency> ``` 这将引入Jackson库XML支持。接下来,我们需要在Spring Boot应用程序添加Jackson XML配置。我们可以使用以下配置: ``` @Configuration public class JacksonConfig { @Bean public ObjectMapper xmlMapper() { //创建用于xml序列化和反序列化的ObjectMapper实例 XmlMapper xmlMapper = new XmlMapper(); //设置要忽略的属性 xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); xmlMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); //用于处理“反序列化空字符串”异常的配置。否则在将空字符串转换为数字或布尔型时会抛出异常。 xmlMapper.registerModule(new SimpleModule() {{ addDeserializer(String.class, new StdScalarDeserializer<>(String.class) { @Override public String deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { return StringUtils.trimToNull(parser.getValueAsString()); } }); }}); return xmlMapper; } @Bean public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.xml(); builder.modulesToInstall(new JavaTimeModule()); builder.indentOutput(true); builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); return builder; } } ``` 上述配置创建一个ObjectMapper实例,并为其配置Jackson XML支持。然后我们可以使用该实例进行Java对象XML之间转换。 例如,我们可以使用如下代码将XML字符串转换Java对象: ``` String xmlString = "<person><name>John Doe</name><age>30</age></person>"; Person person = xmlMapper().readValue(xmlString, Person.class); ``` 其Person是一个Java类,用于表示一个人的信息。反之,我们可以使用以下代码将Java对象转换XML字符串: ``` Person person = new Person("John Doe", 30); String xmlString = xmlMapper().writeValueAsString(person); ``` 最后,我们可以使用相同的方式来进行JSON和Java对象之间转换。只需使用Jackson库的ObjectMapper类就可以实现。例如,我们可以使用以下代码将JSON字符串转换Java对象: ``` String jsonString = "{\"name\":\"John Doe\",\"age\":30}"; Person person = new ObjectMapper().readValue(jsonString, Person.class); ``` 反之,我们可以使用以下代码将Java对象转换为JSON字符串: ``` Person person = new Person("John Doe", 30); String jsonString = new ObjectMapper().writeValueAsString(person); ``` 需要注意的是,我们需要在pom.xml文件引入Jackson库的JSON支持: ``` <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.3</version> </dependency> ``` 总之,使用Spring Boot和Jackson库,我们可以轻松地实现XML和JSON之间转换。这使得我们可以方便地在Java应用程序处理XML和JSON数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值