2016-02-10 2 views
1

У меня есть два класса на данный момент. Customer и CustomerItem, каждый Customer может содержать несколько CustomerItems:Unmarshalling, если поток содержит коллекцию?

@XmlRootElement(name = "Customer") 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Customer implements Serializable { 

    private final String customerNumber; 
    private final String customerName; 

    @XmlElementWrapper(name = "customerItems") 
    @XmlElement(name = "CustomerItem") 
    private List<CustomerItem> customerItems; 
... 

Via REST мы можем получить List<Customer>, что приведет в XML выглядит как что:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<collection> 
    <Customer> 
    // normal values 
    <customerItems> 
     <customerItem> 
     // normal values 
     </customerItem> 
    </customerItems> 
    </Customer> 
    <Customer> 
    ... 
    </Customer> 
    <Customer> 
    ... 
    </Customer> 
</collection> 

Теперь, если я хочу, чтобы распаковать ответ я получаю сообщение об ошибке:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"collection"). Expected elements are <{}Customer>,<{}CustomerItem>

private List<Customer> getCustomersFromResponse(HttpResponse response) 
    throws JAXBException, IllegalStateException, IOException { 

    JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class); 
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
    InputStream content = response.getEntity().getContent(); 
    InputStreamReader reader = new InputStreamReader(content); 

    java.util.List<Customer> unmarshal = (List<Customer>) jaxbUnmarshaller.unmarshal(reader); 
    return unmarshal; 

} 

Теперь я знаю, почему он не работает, очевидно, что Jaxb ожидает, что Клиент станет корневым элементом, но теперь найдите коллекцию (которая, кажется, является значением по умолчанию при возврате списка?).

Обходным путем было бы создать новый класс Customers, который содержит список клиентов и сделать его корневым элементом, но на самом деле я бы не хотел новый класс.

Должен быть способ сообщить jaxb, что у меня есть список классов, которые я хочу получить, и что он должен заглянуть в тег коллекции или что-то в этом роде ?!

ответ

1

Я вижу здесь два пути.

1) Создайте специальный класс обертки с @XmlRootElement(name = "collection") и установите его против unmarshaller.

2) Другой способ - разделение входного сигнала на более мелкие xml один, используя простую реализацию SAX синтаксического анализатора, а затем разобрать каждый фрагмент отдельно с помощью JAXB (см: Split 1GB Xml file using Java).

Я не думаю, что вы можете просто сказать JAXB: проанализируйте это xml как набор элементов типа XXX.

+0

Спасибо, предположим, что нам нужно пойти с классом-оболочкой. – Feroc

Смежные вопросы