@XmlJavaTypeAdapter,Inheritance和xsi:type

时间:2013-04-12 18:52:43

标签: jaxb eclipselink moxy

好的就是当我执行以下操作时会发生什么:

Entities.java:所有名称以“E”开头的类(例如EStudent,ETeacher等)扩展EntityWithId类。

public class Entities {

  Map<Integer,EStudent> students;
  Map<Integer,ETeacher> teachers;
  Map<Integer,ECourse> courses;
  Map<Integer,EQuiz> quizzes;
  Map<Integer,EQuestion> questions;
  Map<Integer,EAnswer> answers;
  Map<Integer,ETimeslot> timeslots;
  Map<Integer,ESharedFile> sharedFiles;

  ...
}

entities-xml-bindings.xml:我为所有属性设置了xml-java-type-adapter。省略了。

<?xml version="1.0" encoding="US-ASCII"?>
  <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="com.pest.esinif.common.entity">

<java-types>
    <java-type name="Entities">
        <java-attributes>
            <xml-element java-attribute="students" >
                <xml-java-type-adapter value="com.pest.esinif.common.entity.adapters.MapToCollectionAdapter" />
            </xml-element>
            ...
        </java-attributes>
    </java-type>
</java-types>
</xml-bindings>

MapToCollectionAdapter.java:打算将地图转换为集合。

public class MapToCollectionAdapter extends XmlAdapter<MyCollection, Map<Integer,EntityWithId>> {

@Override
public Map<Integer, EntityWithId> unmarshal(MyCollection v) throws Exception {
    Map<Integer, EntityWithId> m = new TreeMap<>();

    for (Iterator<EntityWithId> it = v.list.iterator(); it.hasNext();) {
        EntityWithId i = it.next();
        m.put(i.getId(), i);
    }

    return m;
}

@Override
public MyCollection marshal(Map<Integer, EntityWithId> v) throws Exception {
    if(v == null) {
        return null;
    }
    MyCollection mc = new MyCollection();
    mc.list = v.values();
    return mc;
}

class MyCollection {

  @XmlElement(name="entry")
  public Collection<EntityWithId> list;

  public MyCollection() {}
}

当我编组时,输出如下。

<?xml version="1.0" encoding="UTF-8"?>
<entities>
   <courses>
      <entry id="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eCourse">
         <name>English</name>
         <timetable>5</timetable>
         <timetable>6</timetable>
      </entry>
   </courses>
   <students>
      <entry id="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eStudent">
         <name>Anil Anar</name>
      </entry>
   </students>
   <timeslots>
      <entry id="12" course="4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="eTimeslot">
         <attendances>1</attendances>
         <day>1970-01-01T02:00:00.0</day>
         <slot>0</slot>
      </entry>
   </timeslots>
</entities>

你注意到那些xsi:type了吗?当我省略它们时,unmarshaller显然会失败。但我不希望所有<entry>标签都有。我更喜欢它如下:

<courses child-xsi-type="eCourse">
    <entry> ... </entry>
    <entry> ... </entry>
</courses>

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

由于Blaise Doughan's blogs,我解决了这个问题。诀窍是使用@XmlAnyElement(lax=true)并使用EntityWithId注释@XmlRootElement的子类。

class MyCollection {

  @XmlAnyElement(lax=true)
  public Collection<EntityWithId> list;

  public MyCollection() {}
}

输出我得到:

<?xml version="1.0" encoding="UTF-8"?>
<entities>
   <courses>
      <course id="4">
         <name>English</name>
         <timetable>5</timetable>
         <timetable>6</timetable>
      </course>
   </courses>
   <students>
      <student id="1">
         <name>Anil Anar</name>
      </student>
   </students>
   <timeslots>
      <timeslot id="12">
         <attendances>1</attendances>
         <day>1970-01-01T02:00:00.0</day>
         <slot>0</slot>
      </timeslot>
   </timeslots>
</entities>