XStream同名alias解析冲突

当存在多个同名alias注解的Model(对应XML根标签相同)时,XStream解析会产生冲突,需要生成各自的XStream对象来解析

参考:https://github.com/x-stream/xstream/issues/130

public final class XmlUtil {
  private final static ConcurrentMap<Class<?>, XStream> XSTREAMS = new ConcurrentHashMap<>();
  private final static HierarchicalStreamDriver DRIVER = new XppDriver(new XmlFriendlyNameCoder("-", ""));
  private XStream getXStream(Class<?> type) {
    return XSTREAMS.computeIfAbsent(type, t -> {
      XStream xstream = new XStream(DRIVER);
      xstream.processAnnotations(t);
      xstream.allowTypes(new Class[]{t});
      return xstream;
    })
  }
  public static <T> T xmlToObject(String xml, Class<? extends IRequest> cls) {
    return (T)getXStream(cls).fromXml(xml);
  }
}

import com.lianlian.global.thai.provider.channel.gateway.alipay.transactionqrcode.model.response.AlipayCancelReturn;
import com.lianlian.global.thai.provider.channel.gateway.alipay.transactionqrcode.model.response.AlipayCreateReturn;
import com.lianlian.global.thai.provider.channel.gateway.alipay.transactionqrcode.model.response.AlipayQueryReturn;
import com.lianlian.global.thai.provider.channel.gateway.alipay.transactionqrcode.model.response.AlipayRefundReturn;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

@Slf4j
@Component
public class XStreamHelper {

    private XStream xStream = new XStream(new XppDriver(new XmlFriendlyNameCoder("_-", "_"))); //解决下划线问题
    private final static ConcurrentMap<Class<?>, XStream> xStreamMap = new ConcurrentHashMap<>();
    private final static HierarchicalStreamDriver DRIVER = new XppDriver(new XmlFriendlyNameCoder("_-", "_"));

    private XStream getXStream(Class<?> type) {
        return xStreamMap.computeIfAbsent(type, t -> {
            XStream xStream = new XStream(DRIVER);
            xStream.processAnnotations(t);
            xStream.allowTypes(new Class[]{t});
            return xStream;
        });
    }

    public AlipayCreateReturn parseAlipayCreateReturn(String response) {
        XStream xStream = getXStream(AlipayCreateReturn.class);
        //com.thoughtworks.xstream.mapper.CannotResolveClassException: alipay
        xStream.alias("alipay", AlipayCreateReturn.class);
        //com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field
        xStream.autodetectAnnotations(true); //自动检测注解
        xStream.processAnnotations(AlipayCreateReturn.class); //应用Bean类的注解
        AlipayCreateReturn alipayCreateReturn = (AlipayCreateReturn) xStream.fromXML(response);
        log.info(alipayCreateReturn.toString());
        return alipayCreateReturn;
    }

    public AlipayRefundReturn parseAlipayRefundReturn(String response) {
        XStream xStream = getXStream(AlipayRefundReturn.class);
        //com.thoughtworks.xstream.mapper.CannotResolveClassException: alipay
        xStream.alias("alipay", AlipayRefundReturn.class);
        //com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field
        xStream.autodetectAnnotations(true); //自动检测注解
        xStream.processAnnotations(AlipayRefundReturn.class); //应用Bean类的注解
        AlipayRefundReturn alipayRefundReturn = (AlipayRefundReturn) xStream.fromXML(response);
        log.info(alipayRefundReturn.toString());
        return alipayRefundReturn;
    }

    public AlipayQueryReturn parseAlipayQueryReturn(String response) {
        XStream xStream = getXStream(AlipayQueryReturn.class);
        //com.thoughtworks.xstream.mapper.CannotResolveClassException: alipay
        xStream.alias("alipay", AlipayQueryReturn.class);
        //com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field
        xStream.autodetectAnnotations(true); //自动检测注解
        xStream.processAnnotations(AlipayQueryReturn.class); //应用Bean类的注解
        AlipayQueryReturn alipayQueryReturn = (AlipayQueryReturn) xStream.fromXML(response);
        log.info(alipayQueryReturn.toString());
        return alipayQueryReturn;
    }

    public AlipayCancelReturn parseAlipayCancelReturn(String response) {
        XStream xStream = getXStream(AlipayCancelReturn.class);
        //com.thoughtworks.xstream.mapper.CannotResolveClassException: alipay
        xStream.alias("alipay", AlipayCancelReturn.class);
        //com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field
        xStream.autodetectAnnotations(true); //自动检测注解
        xStream.processAnnotations(AlipayCancelReturn.class); //应用Bean类的注解
        AlipayCancelReturn alipayCancelReturn = (AlipayCancelReturn) xStream.fromXML(response);
        log.info(alipayCancelReturn.toString());
        return alipayCancelReturn;
    }
}

AlipayCreateReturn.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@XStreamAlias("alipay")
public class AlipayCreateReturn {

    @XStreamAlias("is_success")
    private String isSuccess;

    @XStreamAlias("error")
    private String error;

    @XStreamAlias("request")
    private Request request;

    @XStreamAlias("response")
    private Response response;

    @XStreamAlias("sign_type")
    private String signType;

    private String sign;

    @Data
    @NoArgsConstructor
    public static class Request {
        @XStreamImplicit(itemFieldName = "param")
        private List<Param> param;
    }

    @Data
    @NoArgsConstructor
    @XStreamAlias("param")
    @XStreamConverter(value = ToAttributedValueConverter.class, strings = {"content"})
    public static class Param {
        @XStreamAsAttribute
        private String name;
        private String content;
    }

    @Data
    @NoArgsConstructor
    public static class Response {
        @XStreamAlias("alipay")
        private AlipayResponse alipayResponse;
    }

    @Data
    @NoArgsConstructor
    public static class AlipayResponse {
        @XStreamAlias("result_code")
        private String resultCode;
        @XStreamAlias("error")
        private String error;
        @XStreamAlias("detail_error_code")
        private String detailErrorCode;
        @XStreamAlias("detail_error_des")
        private String detailErrorDes;
        @XStreamAlias("display_message")
        private String displayMessage;

        @XStreamAlias("out_trade_no")
        private String outTradeNo;
        @XStreamAlias("qr_code")
        private String qrCode;
        @XStreamAlias("big_pic_url")
        private String bigPicUrl;
        @XStreamAlias("pic_url")
        private String picUrl;
        @XStreamAlias("small_pic_url")
        private String smallPicUrl;
        @XStreamAlias("voucher_type")
        private String voucherType;
    }
}

AlipayRefundReturn.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@XStreamAlias("alipay")
public class AlipayRefundReturn {

    @XStreamAlias("is_success")
    private String isSuccess;

    @XStreamAlias("error")
    private String error;

    @XStreamAlias("request")
    private AlipayCreateReturn.Request request;

    @XStreamAlias("response")
    private Response response;

    @XStreamAlias("sign_type")
    private String signType;

    private String sign;

    @Data
    @NoArgsConstructor
    public static class Request {
        @XStreamImplicit(itemFieldName = "param")
        private List<Param> param;
    }

    @Data
    @NoArgsConstructor
    @XStreamAlias("param")
    @XStreamConverter(value = ToAttributedValueConverter.class, strings = {"content"})
    public static class Param {
        @XStreamAsAttribute
        private String name;
        private String content;
    }

    @Data
    @NoArgsConstructor
    public static class Response {
        @XStreamAlias("alipay")
        private AlipayResponse alipayResponse;
    }

    @Data
    @NoArgsConstructor
    public static class AlipayResponse {
        @XStreamAlias("result_code")
        private String resultCode;
        @XStreamAlias("error")
        private String error;
        @XStreamAlias("detail_error_code")
        private String detailErrorCode;
        @XStreamAlias("detail_error_des")
        private String detailErrorDes;
        @XStreamAlias("display_message")
        private String displayMessage;

        @XStreamAlias("alipay_trans_id")
        private String alipayTransId;
        @XStreamAlias("currency")
        private String currency;
        @XStreamAlias("exchange_rate")
        private String exchangeRate;
        @XStreamAlias("partner_refund_id")
        private String partnerRefundId;
        @XStreamAlias("partner_trans_id")
        private String partnerTransId;
        @XStreamAlias("refund_amount")
        private String refundAmount;
        @XStreamAlias("refund_amount_cny")
        private String refundAmountCny;
    }
}

AlipayQueryReturn.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@XStreamAlias("alipay")
public class AlipayQueryReturn {

    @XStreamAlias("is_success")
    private String isSuccess;

    @XStreamAlias("error")
    private String error;

    @XStreamAlias("request")
    private Request request;

    @XStreamAlias("response")
    private Response response;

    @XStreamAlias("sign_type")
    private String signType;

    private String sign;

    @Data
    @NoArgsConstructor
    public static class Request {
        @XStreamImplicit(itemFieldName = "param")
        private List<Param> param;
    }

    @Data
    @NoArgsConstructor
    @XStreamAlias("param")
    @XStreamConverter(value = ToAttributedValueConverter.class, strings = {"content"})
    public static class Param {
        @XStreamAsAttribute
        private String name;
        private String content;
    }

    @Data
    @NoArgsConstructor
    public static class Response {
        @XStreamAlias("alipay")
        private AlipayResponse alipayResponse;
    }

    @Data
    @NoArgsConstructor
    public static class AlipayResponse {
        @XStreamAlias("result_code")
        private String resultCode;
        @XStreamAlias("error")
        private String error;
        @XStreamAlias("detail_error_code")
        private String detailErrorCode;
        @XStreamAlias("detail_error_des")
        private String detailErrorDes;
        @XStreamAlias("display_message")
        private String displayMessage;

        @XStreamAlias("alipay_buyer_login_id")
        private String alipayBuyerLoginId;
        @XStreamAlias("alipay_buyer_user_id")
        private String alipayBuyerUserId;
        @XStreamAlias("alipay_pay_time")
        private String alipayPayTime;
        @XStreamAlias("alipay_trans_id")
        private String alipayTransId;
        @XStreamAlias("alipay_trans_status")
        private String alipayTransStatus;
        @XStreamAlias("currency")
        private String currency;
        @XStreamAlias("exchange_rate")
        private String exchangeRate;
        @XStreamAlias("forex_total_fee")
        private String forexTotalFee;
        @XStreamAlias("out_trade_no")
        private String outTradeNo;
        @XStreamAlias("partner_trans_id")
        private String partnerTransId;
        @XStreamAlias("trans_amount")
        private String transAmount;
        @XStreamAlias("trans_amount_cny")
        private String transAmountCny;
        @XStreamAlias("trans_forex_rate")
        private String transForexRate;

    }
}

AlipayCancelReturn.java

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
@XStreamAlias("alipay")
public class AlipayCancelReturn {

    @XStreamAlias("is_success")
    private String isSuccess;

    @XStreamAlias("error")
    private String error;

    @XStreamAlias("request")
    private Request request;

    @XStreamAlias("response")
    private Response response;

    @XStreamAlias("sign_type")
    private String signType;

    private String sign;

    @Data
    @NoArgsConstructor
    public static class Request {
        @XStreamImplicit(itemFieldName = "param")
        private List<Param> param;
    }

    @Data
    @NoArgsConstructor
    @XStreamAlias("param")
    @XStreamConverter(value = ToAttributedValueConverter.class, strings = {"content"})
    public static class Param {
        @XStreamAsAttribute
        private String name;
        private String content;
    }

    @Data
    @NoArgsConstructor
    public static class Response {
        @XStreamAlias("alipay")
        private AlipayResponse alipayResponse;
    }

    @Data
    @NoArgsConstructor
    public static class AlipayResponse {
        @XStreamAlias("result_code")
        private String resultCode;
        @XStreamAlias("error")
        private String error;
        @XStreamAlias("detail_error_code")
        private String detailErrorCode;
        @XStreamAlias("detail_error_des")
        private String detailErrorDes;
        @XStreamAlias("display_message")
        private String displayMessage;

        @XStreamAlias("out_trade_no")
        private String outTradeNo;
        @XStreamAlias("retry_flag")
        private String retryFlag;
    }
}

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/19/xstream-alias-parsing-conflict-with-same-name/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
XStream同名alias解析冲突
当存在多个同名alias注解的Model(对应XML根标签相同)时,XStream解析会产生冲突,需要生成各自的XStream对象来解析 参考:https://github.com/x-stream/xstr……
<<上一篇
下一篇>>
文章目录
关闭
目 录