Гибкий синтаксический анализ JAXB XML для обобщений и определенного типа или списка этого типа - PullRequest
0 голосов
/ 30 января 2019

Я работаю с API коллеги.API возвращает Response со списком объектов или только одним единственным объектом.Объекты могут быть нескольких типов.Тип возвращаемого значения в XML.Я заинтересован в синтаксическом анализе этого XML через JAXB для получения моих классов, в идеале гибким и универсальным способом.

Следующие два XML-ответа являются примером того, о чем я говорю.

Пример1: Ответ со списком Jobs, содержащий Job объект.

<Response>
   <Status>OK</Status>
   <Jobs>
        <Job>
            <ID>J1</ID>
            <Name>job name</Name> 
        </Job>
        <Job>
            <ID>J2</ID>
            <Name>job name</Name> 
        </Job>
    </Jobs>
</Response>

Пример 2: Ответ с одним Job.

<Response>
    <Status>OK</Status> 
    <Job>
        <ID>J123</ID> 
        <Name>job name</Name> 
    </Job>
</Response>

В данный момент яЯ создаю что-то следующим образом:

@XmlRootElement(name="Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
    @XmlElement(name = "Status")
    protected Status status;
    @XmlAnyElement(lax=true)
    protected Object items;
}

Unmarshalling через

   Response = (Response) unmarshaller.unmarshal(myXmlResponse);

Но я получаю null в своих предметах при немаршаллинге Sample 1.Кроме того, такой подход вызывает у меня плохое предчувствие, поскольку я использую Object в качестве универсального решения, то есть ожидаю оба типа List<Job> и Job.Что я делаю неправильно?Есть ли лучшее решение?Может быть, мой класс ответа может иметь два обобщенных типа: один для списка item с и другой для одного item?

Подход, при котором единственное число <Job> преобразуется в список jobs с одним элементом также было бы интересно, но я не уверен, что это может быть универсальным без изменения ответа XML.

1 Ответ

0 голосов
/ 31 января 2019

Вы можете сделать это:

@XmlRootElement(name = "Response")
public class Response {

    @XmlElement(name ="Status")
    private Status status;

    @XmlElements({
            @XmlElement(name = "Job", type = Job.class),
            @XmlElement(name = "Jobs", type = Jobs.class),
    })
    private List<?> jobs;
}

Тогда задание будет:

public class Job {

    @XmlElement(name = "ID")
    private String id;
    @XmlElement(name = "Name")
    private String name;
}

И Вакансии:

public class Jobs {

    @XmlElement(name = "Job")
    private List<Job> jobs;
}

Обновление для ответа на комментарий:

Это самый чистый способ обработки описанных полезных нагрузок.Задача в том, чтобы <Jobs></Jobs> был там только несколько раз.

Есть способ сделать это без встроенного списка, но это сложнее.Я скопирую его ниже, чтобы вы могли решить, нравится ли вам это или лучше найти другое более чистое решение.

@XmlRootElement(name = "Response")
public class Response {

    @XmlElement(name ="Status")
    private Status status;

    @XmlElement(name = "Job")
    private List<Job> jobs;

    @XmlElementWrapper(name = "Jobs")
    @XmlElement(name = "Job")
    private List<Job> jobsWrapped;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...