灵活的 JAXB XML 解析泛型和特定类型或该类型的列表
Flexible JAXB XML parsing for generics and a particular type or a list of that type
我正在和一位同事的 API 一起工作。 API return 是一个 Response
,其中包含对象列表或只有一个对象。对象可以是多种类型。 return 类型在 XML 中。我有兴趣通过 JAXB 解析此 XML 以获得我的 classes,理想情况下是以灵活和通用的方式。
以下两个 XML 回复是我所说内容的示例。
示例 1:包含 Job
对象的列表 Jobs
的响应。
<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;
}
解组通过
Response = (Response) unmarshaller.unmarshal(myXmlResponse);
但在解组 Sample 1
时,我的项目中收到了 null
。此外,这种方法给我一种不好的感觉,因为我使用 Object
作为包罗万象,即期望 List<Job>
和 Job
类型。我究竟做错了什么?有更好的解决方案吗?也许我的回复 class 可以有两个泛型,一个用于 item
列表,另一个用于单个 item
?
将单数 <Job>
转换为具有一个元素的 job
列表的方法也很有趣,但我不确定如果不修改XML 响应。
你可以这样做:
@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;
}
我正在和一位同事的 API 一起工作。 API return 是一个 Response
,其中包含对象列表或只有一个对象。对象可以是多种类型。 return 类型在 XML 中。我有兴趣通过 JAXB 解析此 XML 以获得我的 classes,理想情况下是以灵活和通用的方式。
以下两个 XML 回复是我所说内容的示例。
示例 1:包含 Job
对象的列表 Jobs
的响应。
<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;
}
解组通过
Response = (Response) unmarshaller.unmarshal(myXmlResponse);
但在解组 Sample 1
时,我的项目中收到了 null
。此外,这种方法给我一种不好的感觉,因为我使用 Object
作为包罗万象,即期望 List<Job>
和 Job
类型。我究竟做错了什么?有更好的解决方案吗?也许我的回复 class 可以有两个泛型,一个用于 item
列表,另一个用于单个 item
?
将单数 <Job>
转换为具有一个元素的 job
列表的方法也很有趣,但我不确定如果不修改XML 响应。
你可以这样做:
@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;
}