具有相同名称的JAXB @XmlRootElement

时间:2018-09-07 08:16:19

标签: java jaxb classcastexception jaxb2

我有一个很长的XML,例如:

<Author>
    <id></id>
    <name></name>
    <title></title>
    <address></address>
     ....
</Author>

我以前使用JAXB来解析XML。

JAXBContext.newInstance(Author.class);

还有我的Author.java

@XmlRootElement(name = "Author")
public class Author {
     private String id;
     private String name;
     private String title;
     private String address;
     ...
}

它运作良好,但我不想每次都将整个XML解析为一个大型Java bean。

所以,我想使用以下方式:

创建Commentator.java

@XmlRootElement(name = "Author")
public class Commentator {
     private String id;
     private String name;
     // setters, getters
}

创建Analyst.java

@XmlRootElement(name = "Author")
public class Analyst {
     private String title;
     private String address;
     // setters, getters
}

然后我编写以下代码进行测试。

JAXBContext context = JAXBContext.newInstance(Analyst.class, Commentator.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
String xml = "<Author> <id>1</id> <name>A</name> <title>B</title> <address>C</address></Author>";
Commentator obj = (Commentator) unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));
System.out.println(obj);

它将打印正确的胶卷。

如果我想获得分析师。

Analyst a = (Analyst) unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));

我会得到以下例外:java.lang.ClassCastException: com.xxx.Commentator cannot be cast to com.xxx.Analyst

我不确定解析器是否正确。但是我真的需要这样的功能。

2 个答案:

答案 0 :(得分:1)

只需找到一种快速的方法即可完成

  1. 注册pojo。

JAXBContext context = JAXBContext.newInstance(Analyst.class, Commentator.class);

  1. 处理输入。我将str-xml转换为StreamSource。
String xml = "<Author> <id>1</id> <name>A</name> <title>B</title> <address>C</address></Author>";
StreamSource source = new StreamSource(new ByteArrayInputStream(xml.getBytes()));
  1. 创建解组器。

Unmarshaller unmarshaller = context.createUnmarshaller();

  1. (重要)解组数据时,提供第二个参数(要解组的类)

JAXBElement<Analyst> unmarshal = unmarshaller.unmarshal(source, Analyst.class);

然后,得到您想要的东西:

Analyst analyst = unmarshal.getValue();

  1. 如果需要另一个pojo。(请注意,unmarshallersource不能在方法中重复使用)

JAXBElement<Commentator> unmarshal2 = unmarshaller2.unmarshal(source2, Commentator.class);

然后:

Commentator com = unmarshal2.getValue();

无错误报告,结果正确。

答案 1 :(得分:0)

在我看来,映射多个Java类有点笨拙 具有相同的@XmlRootElement。 但是,尽管如此,您仍然能够实现所需的目标。

JAXBContextAnalyst需要不同的Commentator
而且,由于JAXBContext是一个大对象,而JAXBContext.newInstance(...)的执行时间很长, 将这些JAXBContext实例保存在static变量中是有意义的 并重用这些而不是创建新的:

private static JAXBContext analystContext;
private static JAXBContext commentatorContext;

if (analystContext == null)
    analystContext = JAXBContext.newInstance(Analyst.class);
if (commentatorContext == null)
    commentatorContext = JAXBContext.newInstance(Commentator.class);

因此,您还需要根据它们创建不同的Unmarshaller

Unmarshaller analystUnmarshaller = analystContext.createUnmarshaller();
Unmarshaller commentatorUnmarshaller = commentatorContext.createUnmarshaller();

然后,您可以将相同的XML内容解组到不同的根类:

String xml = "<Author> <id>1</id> <name>A</name> <title>B</title> <address>C</address></Author>";
Analyst analyst = (Analyst) analystUnmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));
Commentator commentator = (Commentator) commentatorUnmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes()));