【问题标题】:JAXB marshalling and inheritanceJAXB 编组和继承
【发布时间】:2014-01-03 16:26:31
【问题描述】:

我有 2 个类,一个扩展另一个。超类正确编组,但添加一个属性的子类没有。 XML 中不存在额外属性。

超类:

@XmlRootElement()
@XmlAccessorType(XmlAccessType.NONE)
public class SessionRecord extends Record {

  SimpleDateFormat hhmm = new SimpleDateFormat("HH:mm");
  SimpleDateFormat day = new SimpleDateFormat("EEEEE");

  @XmlAttribute protected int sessionId;
  @XmlAttribute protected boolean open;
  @XmlAttribute protected boolean night;
  protected Date start;
  protected Date finish;
  protected boolean setup;
  protected boolean takedown;

  @XmlAttribute
  public String getDescription() {
        if (start==null) start = new Date();
        if (finish==null) finish = new Date();
        return day.format(start)+(night ? " Night " : " ")+hhmm.format(start)+"-"+hhmm.format(finish)+" "+type();
  }

  private String type() {
        return setup ? "Setup" : (open ? "Open" : (takedown ? "Takedown" : ""));
  }

  @XmlAttribute
  public boolean isSetupTakedown() {
        return setup || takedown;
  }

}

这会产生类似这样的 XML 元素:

<sessionRecord setupTakedown="true" description="Saturday 09:00-13:00 Setup" night="false" open="false" sessionId="0"/>

没关系。

但是子类:

@XmlRootElement()
public class VolunteerSession extends SessionRecord {

  @XmlAttribute private boolean available;

}

产生相同的输出,available 属性未编组。为什么 JAXB 不编组额外属性?

编辑

更多信息:

记录超类只是这样:

public abstract class Record {}

这是代表顶级文档元素的类。它包含记录列表:

@XmlRootElement(name="response")
@XmlSeeAlso({
  RecordList.class, 
  VolunteerAssignment.class, 
  VolunteerRecord.class,
  SessionRecord.class,
  VolunteerSession.class,
  VolunteerArea.class,
  PossibleAssignment.class})
public class XMLResponse {

  @XmlAttribute private String errorMessage;

  private List<RecordList<? extends Record>> recordLists  = new ArrayList<RecordList<? extends Record>>();

  //snip...

  public void setError(String errorMessage) {
        this.errorMessage = errorMessage;
  }

  @XmlMixed
  public List<RecordList<? extends Record>> getRecordLists() {
        return recordLists;
  }

}

最后是记录列表

@XmlRootElement()
public class RecordList<T extends Record> {

  @XmlAttribute private String name;
  @XmlAttribute private int total;
  @XmlAttribute private int count;
  @XmlAttribute private int start;
  @XmlAttribute private boolean update;
  private List<T> records;

  // snip constructors, setters

  @XmlMixed
  public List<T> getRecords() {
        return records;
  }

}

【问题讨论】:

  • 尝试在您的 VolunteerSession 类中添加可用的 getter 和 setter。
  • 试过了,没区别
  • 您能否添加您的Record 课程以及如何创建您的JAXBContext
  • 根据要求添加了额外信息。实际上@XmlSeeAlso 是在 XMLResponse 中,而不是我之前说的 Record,但这不应该造成太大的差异

标签: java inheritance jaxb


【解决方案1】:

听起来VolunteerSession 类没有包含在JAXBContext 中。这取决于您创建JAXBContext 的方式。下面是一些示例代码,其中基于 JAXBContext 的 3 个不同实例对同一对象进行编组,每个实例从不同的类引导。

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        VolunteerSession volunteerSession = new VolunteerSession();

        marshal(VolunteerSession.class, volunteerSession);
        marshal(SessionRecord.class, volunteerSession);
        marshal(XMLResponse.class, volunteerSession);
    }

    private static void marshal(Class bootstrapClass, Object object) throws Exception {
        System.out.println(bootstrapClass.getName());
        JAXBContext jc = JAXBContext.newInstance(bootstrapClass);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(object, System.out);
        System.out.println();
    }

}

输出

  1. JAXBContextVolunteerSession 引导出来时,显然它有必要的信息。
  2. JAXBContext 被引导出超类SessionRecord 时,它不会拉入VolunteerSession。 JAXB 将自动处理超类的元数据,而不是子类。在这种情况下,@XmlSeeAlso 通常用于引用映射的子类。
  3. VolunteerRecord 包含一个引用 VolunteerSession@XmlSeeAlso 注释。因此,VolunteerSession 作为JAXBContext 的一部分进行处理,并在编组时包含必要的信息。
forum20908213.VolunteerSession
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<volunteerSession available="false" sessionId="0" open="false" night="false" description="Sunday 05:53-05:53 " setupTakedown="false"/>

forum20908213.SessionRecord
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sessionRecord sessionId="0" open="false" night="false" description="Sunday 05:53-05:53 " setupTakedown="false"/>

forum20908213.XMLResponse
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<volunteerSession available="false" sessionId="0" open="false" night="false" description="Sunday 05:53-05:53 " setupTakedown="false"/>

【讨论】:

  • +1 这很有趣。我不认为我可以访问编组代码本身,因为这一切都是由 Spring MVC 为我完成的。
  • @NickJ - 我认为您的问题的解决方案是添加一个@XmlSeeAlsoVolunteerSessionRecordSessionRecord。我试图在回答中指出的一件事是,根据 JAXBContext 的创建方式,可以创建不同的元数据。
【解决方案2】:

您必须在父类的@XmlSeeAlso 注释中列出所有子类。

【讨论】:

  • 其实我已经做到了。对不起,应该说清楚。它在SessionRecord上方的Record超类中
  • +1 - 您也可以将它们作为用于引导 JAXBContext 的类列表传入。
  • 根据要求添加了额外信息。实际上@XmlSeeAlso 是在 XMLResponse 中,而不是我之前说的 Record,但这不应该造成太大的差异
  • 现在可以正常工作了。不知道我做了什么,但出于某种奇怪的原因,SessionRecord 的 XML 表示还包括 available 属性。不过没关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 1970-01-01
相关资源
最近更新 更多