REST API - 无法使用 JAXB 转换 XML

REST API - Can not convert XML with JAXB

我在处理 API 响应时遇到问题。首先,我正在建立连接以获取我的回复:

HttpResponse<String> response = Unirest.get(buildUrl(newOrdersUrl)).basicAuth(login, pass).asString();
        if(response.getStatus() == 200){
            return OrdersConverter.convertOrders(response.getBody());
        } else {
            return null;
        }

与:

public class OrdersConverter {
    public static OrdersType convertOrders(String response) {
        try {
            JAXBContext jc = JAXBContext.newInstance(OrdersType.class);
            Unmarshaller u = jc.createUnmarshaller();
            StringBuffer xmlStr = new StringBuffer(response);

            JAXBElement<OrdersType> o = u.unmarshal(new StreamSource(new StringReader(xmlStr.toString())), OrdersType.class);

            return o.getValue();
        } catch (JAXBException e) {
            return null;
        }
    }
}

以此https://sell.fruugo.com/fruugo-docs/fruugo-product-feed.xsd作为架构

我的回复字符串看起来像这样(带有经过编辑的信息)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<o:orders merchantId="Redacted" xmlns:o="https://www.fruugo.com/orders/schema">
    <o:order>
        <o:customerOrderId>Redacted</o:customerOrderId>
        <o:orderId>Redacted</o:orderId>
        <o:orderDate>Redacted</o:orderDate>
        <o:orderReleaseDate>Redacted</o:orderReleaseDate>
        <o:orderStatus>Redacted</o:orderStatus>
        <o:customerLanguageCode>Redacted</o:customerLanguageCode>
        <o:shippingAddress>
            <o:firstName>Redacted</o:firstName>
            <o:lastName>Redacted</o:lastName>
            <o:streetAddress>Redacted</o:streetAddress>
            <o:city>Redacted</o:city>
            <o:province>Redacted</o:province>
            <o:postalCode>Redacted</o:postalCode>
            <o:countryCode>Redacted</o:countryCode>
            <o:phoneNumber>Redacted</o:phoneNumber>
        </o:shippingAddress>
        <o:shippingMethod>Redacted</o:shippingMethod>
        <o:shippingCostInclVAT>Redacted</o:shippingCostInclVAT>
        <o:shippingCostVAT>Redacted</o:shippingCostVAT>
        <o:orderLines>
            <o:orderLine>
                <o:productId>Redacted</o:productId>
                <o:skuId>Redacted</o:skuId>
                <o:skuName>Redacted</o:skuName>
                <o:fruugoProductId>Redacted</o:fruugoProductId>
                <o:fruugoSkuId>Redacted</o:fruugoSkuId>
                <o:currencyCode>Redacted</o:currencyCode>
                <o:itemPriceInclVat>Redacted</o:itemPriceInclVat>
                <o:itemVat>Redacted</o:itemVat>
                <o:totalPriceInclVat>Redacted</o:totalPriceInclVat>
                <o:totalVat>Redacted</o:totalVat>
                <o:vatPercentage>Redacted</o:vatPercentage>
                <o:totalNumberOfItems>Redacted</o:totalNumberOfItems>
                <o:pendingItems>Redacted</o:pendingItems>
                <o:confirmedItems>Redacted</o:confirmedItems>
                <o:shippedItems>Redacted</o:shippedItems>
                <o:cancelledItems>Redacted</o:cancelledItems>
                <o:returnAnnouncedItems>Redacted</o:returnAnnouncedItems>
                <o:returnedItems>Redacted</o:returnedItems>
                <o:itemsWithException>Redacted</o:itemsWithException>
            </o:orderLine>
        </o:orderLines>
    </o:order>
    <o:order>
        <o:customerOrderId>Redacted</o:customerOrderId>
        <o:orderId>Redacted</o:orderId>
        <o:orderDate>Redacted</o:orderDate>
        <o:orderReleaseDate>Redacted</o:orderReleaseDate>
        <o:orderStatus>Redacted</o:orderStatus>
        <o:customerLanguageCode>Redacted</o:customerLanguageCode>
        <o:shippingAddress>
            <o:firstName>Redacted</o:firstName>
            <o:lastName>Redacted</o:lastName>
            <o:streetAddress>Redacted</o:streetAddress>
            <o:city>Redacted</o:city>
            <o:province>Redacted</o:province>
            <o:postalCode>Redacted</o:postalCode>
            <o:countryCode>Redacted</o:countryCode>
            <o:phoneNumber>Redacted</o:phoneNumber>
        </o:shippingAddress>
        <o:shippingMethod>Redacted</o:shippingMethod>
        <o:shippingCostInclVAT>Redacted</o:shippingCostInclVAT>
        <o:shippingCostVAT>Redacted</o:shippingCostVAT>
        <o:orderLines>
            <o:orderLine>
                <o:productId>Redacted</o:productId>
                <o:skuId>Redacted</o:skuId>
                <o:skuName>Redacted</o:skuName>
                <o:fruugoProductId>Redacted</o:fruugoProductId>
                <o:fruugoSkuId>Redacted</o:fruugoSkuId>
                <o:currencyCode>Redacted</o:currencyCode>
                <o:itemPriceInclVat>Redacted</o:itemPriceInclVat>
                <o:itemVat>Redacted</o:itemVat>
                <o:totalPriceInclVat>Redacted</o:totalPriceInclVat>
                <o:totalVat>Redacted</o:totalVat>
                <o:vatPercentage>Redacted</o:vatPercentage>
                <o:totalNumberOfItems>Redacted</o:totalNumberOfItems>
                <o:pendingItems>Redacted</o:pendingItems>
                <o:confirmedItems>Redacted</o:confirmedItems>
                <o:shippedItems>Redacted</o:shippedItems>
                <o:cancelledItems>Redacted</o:cancelledItems>
                <o:returnAnnouncedItems>Redacted</o:returnAnnouncedItems>
                <o:returnedItems>Redacted</o:returnedItems>
                <o:itemsWithException>Redacted</o:itemsWithException>
            </o:orderLine>
        </o:orderLines>
    </o:order>
    <o:order>
        <o:customerOrderId>Redacted</o:customerOrderId>
        <o:orderId>Redacted</o:orderId>
        <o:orderDate>Redacted</o:orderDate>
        <o:orderReleaseDate>Redacted</o:orderReleaseDate>
        <o:orderStatus>Redacted</o:orderStatus>
        <o:customerLanguageCode>Redacted</o:customerLanguageCode>
        <o:shippingAddress>
            <o:firstName>Redacted</o:firstName>
            <o:lastName>Redacted</o:lastName>
            <o:streetAddress>Redacted</o:streetAddress>
            <o:city>Redacted</o:city>
            <o:province>Redacted</o:province>
            <o:postalCode>Redacted</o:postalCode>
            <o:countryCode>Redacted</o:countryCode>
            <o:phoneNumber>Redacted</o:phoneNumber>
        </o:shippingAddress>
        <o:shippingMethod>Redacted</o:shippingMethod>
        <o:shippingCostInclVAT>Redacted</o:shippingCostInclVAT>
        <o:shippingCostVAT>Redacted</o:shippingCostVAT>
        <o:orderLines>
            <o:orderLine>
                <o:productId>Redacted</o:productId>
                <o:skuId>Redacted</o:skuId>
                <o:skuName>Redacted</o:skuName>
                <o:fruugoProductId>Redacted</o:fruugoProductId>
                <o:fruugoSkuId>Redacted</o:fruugoSkuId>
                <o:currencyCode>Redacted</o:currencyCode>
                <o:itemPriceInclVat>Redacted</o:itemPriceInclVat>
                <o:itemVat>Redacted</o:itemVat>
                <o:totalPriceInclVat>Redacted</o:totalPriceInclVat>
                <o:totalVat>Redacted</o:totalVat>
                <o:vatPercentage>Redacted</o:vatPercentage>
                <o:totalNumberOfItems>Redacted</o:totalNumberOfItems>
                <o:pendingItems>Redacted</o:pendingItems>
                <o:confirmedItems>Redacted</o:confirmedItems>
                <o:shippedItems>Redacted</o:shippedItems>
                <o:cancelledItems>Redacted</o:cancelledItems>
                <o:returnAnnouncedItems>Redacted</o:returnAnnouncedItems>
                <o:returnedItems>Redacted</o:returnedItems>
                <o:itemsWithException>Redacted</o:itemsWithException>
            </o:orderLine>
        </o:orderLines>
    </o:order>
</o:orders>

当我将此响应转换为 OrdersType.class 时,我可以获得我的 merchantID,但我没有从 OrdersType.class 获得订单列表。 我错过了什么?我是否需要将此响应转换为另一个 class 以获取订单列表?

更新:

对象工厂

/**
 * This object contains factory methods for each 
 * Java content interface and Java element interface 
 * generated in the model package. 
 * <p>An ObjectFactory allows you to programatically 
 * construct new instances of the Java representation 
 * for XML content. The Java representation of XML 
 * content can consist of schema derived interfaces 
 * and classes representing the binding of schema 
 * type definitions, element declarations and model 
 * groups.  Factory methods for each of these are 
 * provided in this class.
 * 
 */
@XmlRegistry
public class ObjectFactory {

    private final static QName _Orders_QNAME = new QName("https://www.fruugo.com/orders/schema", "orders");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: model
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link ShippingAddressType }
     * 
     */
    public ShippingAddressType createShippingAddressType() {
        return new ShippingAddressType();
    }

    /**
     * Create an instance of {@link OrderLinesType }
     * 
     */
    public OrderLinesType createOrderLinesType() {
        return new OrderLinesType();
    }

    /**
     * Create an instance of {@link OrderType }
     * 
     */
    public OrderType createOrderType() {
        return new OrderType();
    }

    /**
     * Create an instance of {@link ShipmentLinesType }
     * 
     */
    public ShipmentLinesType createShipmentLinesType() {
        return new ShipmentLinesType();
    }

    /**
     * Create an instance of {@link ShipmentType }
     * 
     */
    public ShipmentType createShipmentType() {
        return new ShipmentType();
    }

    /**
     * Create an instance of {@link ShipmentsType }
     * 
     */
    public ShipmentsType createShipmentsType() {
        return new ShipmentsType();
    }

    /**
     * Create an instance of {@link ShipmentLineType }
     * 
     */
    public ShipmentLineType createShipmentLineType() {
        return new ShipmentLineType();
    }

    /**
     * Create an instance of {@link AttributeType }
     * 
     */
    public AttributeType createAttributeType() {
        return new AttributeType();
    }

    /**
     * Create an instance of {@link AttributesType }
     * 
     */
    public AttributesType createAttributesType() {
        return new AttributesType();
    }

    /**
     * Create an instance of {@link OrdersType }
     * 
     */
    public OrdersType createOrdersType() {
        return new OrdersType();
    }

    /**
     * Create an instance of {@link OrderLineType }
     * 
     */
    public OrderLineType createOrderLineType() {
        return new OrderLineType();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link OrdersType }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "https://www.fruugo.com/orders/schema", name = "orders")
    public static JAXBElement<OrdersType> createOrders(OrdersType value) {
        return new JAXBElement<OrdersType>(_Orders_QNAME, OrdersType.class, null, value);
    }

}

订单类型

/**
 * <p>Java class for OrdersType complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="OrdersType">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="order" type="{https://www.fruugo.com/orders/schema}OrderType" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/sequence>
 *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
 *       &lt;attribute name="merchantId" type="{http://www.w3.org/2001/XMLSchema}string" />
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OrdersType", propOrder = {
    "order"
})
public class OrdersType {

    protected List<OrderType> order;
    @XmlAttribute(name = "version")
    protected String version;
    @XmlAttribute(name = "merchantId")
    protected String merchantId;

    /**
     * Gets the value of the order property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the order property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getOrder().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link OrderType }
     * 
     * 
     */
    public List<OrderType> getOrder() {
        if (order == null) {
            order = new ArrayList<OrderType>();
        }
        return this.order;
    }

    /**
     * Gets the value of the version property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getVersion() {
        return version;
    }

    /**
     * Sets the value of the version property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setVersion(String value) {
        this.version = value;
    }

    /**
     * Gets the value of the merchantId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getMerchantId() {
        return merchantId;
    }

    /**
     * Sets the value of the merchantId property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setMerchantId(String value) {
        this.merchantId = value;
    }

}

订单类型

/**
 * <p>Java class for OrderType complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="OrderType">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="orderId" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="orderDate" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
 *         &lt;element name="orderReleaseDate" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
 *         &lt;element name="orderStatus" type="{https://www.fruugo.com/orders/schema}OrderStatusEnumType"/>
 *         &lt;element name="customerLanguageCode" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="shippingAddress" type="{https://www.fruugo.com/orders/schema}ShippingAddressType"/>
 *         &lt;element name="shippingMethod" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="shippingCostInclVAT" type="{http://www.w3.org/2001/XMLSchema}float"/>
 *         &lt;element name="shippingCostVAT" type="{http://www.w3.org/2001/XMLSchema}float"/>
 *         &lt;element name="orderLines" type="{https://www.fruugo.com/orders/schema}OrderLinesType"/>
 *         &lt;element name="shipments" type="{https://www.fruugo.com/orders/schema}ShipmentsType" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OrderType", propOrder = {
    "orderId",
    "orderDate",
    "orderReleaseDate",
    "orderStatus",
    "customerLanguageCode",
    "shippingAddress",
    "shippingMethod",
    "shippingCostInclVAT",
    "shippingCostVAT",
    "orderLines",
    "shipments"
})
public class OrderType {

    @XmlElement(required = true)
    protected String orderId;
    @XmlElement(required = true)
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar orderDate;
    @XmlElement(required = true)
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar orderReleaseDate;
    @XmlElement(required = true)
    protected OrderStatusEnumType orderStatus;
    @XmlElement(required = true)
    protected String customerLanguageCode;
    @XmlElement(required = true)
    protected ShippingAddressType shippingAddress;
    @XmlElement(required = true)
    protected String shippingMethod;
    protected float shippingCostInclVAT;
    protected float shippingCostVAT;
    @XmlElement(required = true)
    protected OrderLinesType orderLines;
    protected ShipmentsType shipments;

    /**
     * Gets the value of the orderId property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getOrderId() {
        return orderId;
    }

    /**
     * Sets the value of the orderId property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setOrderId(String value) {
        this.orderId = value;
    }

    /**
     * Gets the value of the orderDate property.
     * 
     * @return
     *     possible object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public XMLGregorianCalendar getOrderDate() {
        return orderDate;
    }

    /**
     * Sets the value of the orderDate property.
     * 
     * @param value
     *     allowed object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public void setOrderDate(XMLGregorianCalendar value) {
        this.orderDate = value;
    }

    /**
     * Gets the value of the orderReleaseDate property.
     * 
     * @return
     *     possible object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public XMLGregorianCalendar getOrderReleaseDate() {
        return orderReleaseDate;
    }

    /**
     * Sets the value of the orderReleaseDate property.
     * 
     * @param value
     *     allowed object is
     *     {@link XMLGregorianCalendar }
     *     
     */
    public void setOrderReleaseDate(XMLGregorianCalendar value) {
        this.orderReleaseDate = value;
    }

    /**
     * Gets the value of the orderStatus property.
     * 
     * @return
     *     possible object is
     *     {@link OrderStatusEnumType }
     *     
     */
    public OrderStatusEnumType getOrderStatus() {
        return orderStatus;
    }

    /**
     * Sets the value of the orderStatus property.
     * 
     * @param value
     *     allowed object is
     *     {@link OrderStatusEnumType }
     *     
     */
    public void setOrderStatus(OrderStatusEnumType value) {
        this.orderStatus = value;
    }

    /**
     * Gets the value of the customerLanguageCode property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getCustomerLanguageCode() {
        return customerLanguageCode;
    }

    /**
     * Sets the value of the customerLanguageCode property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setCustomerLanguageCode(String value) {
        this.customerLanguageCode = value;
    }

    /**
     * Gets the value of the shippingAddress property.
     * 
     * @return
     *     possible object is
     *     {@link ShippingAddressType }
     *     
     */
    public ShippingAddressType getShippingAddress() {
        return shippingAddress;
    }

    /**
     * Sets the value of the shippingAddress property.
     * 
     * @param value
     *     allowed object is
     *     {@link ShippingAddressType }
     *     
     */
    public void setShippingAddress(ShippingAddressType value) {
        this.shippingAddress = value;
    }

    /**
     * Gets the value of the shippingMethod property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getShippingMethod() {
        return shippingMethod;
    }

    /**
     * Sets the value of the shippingMethod property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setShippingMethod(String value) {
        this.shippingMethod = value;
    }

    /**
     * Gets the value of the shippingCostInclVAT property.
     * 
     */
    public float getShippingCostInclVAT() {
        return shippingCostInclVAT;
    }

    /**
     * Sets the value of the shippingCostInclVAT property.
     * 
     */
    public void setShippingCostInclVAT(float value) {
        this.shippingCostInclVAT = value;
    }

    /**
     * Gets the value of the shippingCostVAT property.
     * 
     */
    public float getShippingCostVAT() {
        return shippingCostVAT;
    }

    /**
     * Sets the value of the shippingCostVAT property.
     * 
     */
    public void setShippingCostVAT(float value) {
        this.shippingCostVAT = value;
    }

    /**
     * Gets the value of the orderLines property.
     * 
     * @return
     *     possible object is
     *     {@link OrderLinesType }
     *     
     */
    public OrderLinesType getOrderLines() {
        return orderLines;
    }

    /**
     * Sets the value of the orderLines property.
     * 
     * @param value
     *     allowed object is
     *     {@link OrderLinesType }
     *     
     */
    public void setOrderLines(OrderLinesType value) {
        this.orderLines = value;
    }

    /**
     * Gets the value of the shipments property.
     * 
     * @return
     *     possible object is
     *     {@link ShipmentsType }
     *     
     */
    public ShipmentsType getShipments() {
        return shipments;
    }

    /**
     * Sets the value of the shipments property.
     * 
     * @param value
     *     allowed object is
     *     {@link ShipmentsType }
     *     
     */
    public void setShipments(ShipmentsType value) {
        this.shipments = value;
    }

}

我很确定问题出在 xml(响应)的结构与生成的 类 不匹配。

您提供的 xsd 与您在问题中提供的 类 不对应,也不与您尝试解组的 xml 对应。我认为您有一些绑定覆盖了 link 中显示的架构的名称等,并且没有提供所有 类 供我自己尝试。

一种帮助您解决问题的方法是输入 xml 并尝试使用以下代码对其进行解组,您将逐字段获得不匹配的反馈。

        try {
            File file = new File("/path/to/your/file.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(YouRootClassForOrder.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            jaxbUnmarshaller.setEventHandler(
                    new ValidationEventHandler() {
                        public boolean handleEvent(ValidationEvent event ) {
                            throw new RuntimeException(event.getMessage(),
                                    event.getLinkedException());
                        }
                    });
            YouRootClassForOrder pojo = (YouRootClassForOrder) jaxbUnmarshaller.unmarshal(file);
        } catch (JAXBException e) {
            e.printStackTrace();
        }