JAXB复杂映射

时间:2014-10-27 16:40:57

标签: java jaxb jaxb2

我有以下代码:

@XmlRootElement(name = "repository")
@XmlAccessorType(XmlAccessType.FIELD)
public class Repository
{
    @XmlElement (name = "id")
    private String id;

    @XmlElement (name = "policy")
    private String policy;
    ...
}

@XmlRootElement(name = "storage")
@XmlAccessorType(XmlAccessType.FIELD)
public class Storage 
{

    @XmlElement (name = "id")
    private String id;

    /**
     * K: repository.id
     * V: Repository
     */
    @XmlElement (name = "repositories")
    @XmlJavaTypeAdapter(RepositoryMapAdapter.class)
    private Map<String, Repository> repositories = new LinkedHashMap<String, Repository>();
    ...
}

public class DataCenter
{
    /**
     * K: storageId
     * V: storage
     */
    @XmlElement(name = "storages")
    @XmlJavaTypeAdapter(StorageMapAdapter.class)
    //@XStreamAlias(value = "storages")
    private Map<String, Storage> storages = new LinkedHashMap<String, Storage>();

    ...
}

我有以下两个适配器:

public class RepositoryMapAdapter
        extends XmlAdapter<RepositoryMapAdapter.RepositoryMap, Map<String, Repository>>
{

    public static class RepositoryMap
    {
        @XmlVariableNode("id")
        List<RepositoryMapEntry> entries = new ArrayList<RepositoryMapEntry>();
    }

    public static class RepositoryMapEntry
    {
        @XmlAttribute
        public String id;

        @XmlValue
        public Repository repository;
    }

    @Override
    public RepositoryMap marshal(Map<String, Repository> map)
            throws Exception
    {
        RepositoryMap repositoryMap = new RepositoryMap();
        for (Map.Entry<String, Repository> entry : map.entrySet())
        {
            RepositoryMapEntry repositoryMapEntry = new RepositoryMapEntry();
            repositoryMapEntry.id = entry.getKey();
            repositoryMapEntry.repository = entry.getValue();

            System.out.println("Writing repository " + entry.getValue().getId());

            repositoryMap.entries.add(repositoryMapEntry);
        }

        return repositoryMap;
    }

    @Override
    public Map<String, Repository> unmarshal(RepositoryMap repositoryMap)
            throws Exception
    {
        List<RepositoryMapEntry> adaptedEntries = repositoryMap.entries;

        Map<String, Repository> map = new LinkedHashMap<String, Repository>(adaptedEntries.size());
        for (RepositoryMapEntry repositoryMapEntry : adaptedEntries)
        {
            System.out.println("Reading repository " + repositoryMapEntry.id);
            map.put(repositoryMapEntry.id, repositoryMapEntry.repository);
        }

        return map;
    }

}

public class StorageMapAdapter
        extends XmlAdapter<StorageMapAdapter.StorageMap, Map<String, Storage>>
{

    public static class StorageMap
    {
        @XmlVariableNode("id")
        List<StorageMapEntry> entries = new ArrayList<StorageMapEntry>();
    }

    public static class StorageMapEntry
    {
        @XmlAttribute
        public String id;

        @XmlValue
        public Storage storage;
    }

    @Override
    public StorageMap marshal(Map<String, Storage> map)
            throws Exception
    {
        StorageMap storageMap = new StorageMap();
        for (Map.Entry<String, Storage> entry : map.entrySet())
        {
            StorageMapEntry storageMapEntry = new StorageMapEntry();
            storageMapEntry.id = entry.getKey();
            storageMapEntry.storage = entry.getValue();

            System.out.println("Writing storage " + entry.getValue().getId());

            storageMap.entries.add(storageMapEntry);
        }

        return storageMap;
    }

    @Override
    public Map<String, Storage> unmarshal(StorageMap storageMap)
            throws Exception
    {
        List<StorageMapEntry> adaptedEntries = storageMap.entries;

        Map<String, Storage> map = new LinkedHashMap<String, Storage>(adaptedEntries.size());
        for (StorageMapEntry storageMapEntry : adaptedEntries)
        {
            System.out.println("Reading storage " + storageMapEntry.id);
            map.put(storageMapEntry.id, storageMapEntry.storage);
        }

        return map;
    }

}

我想要以下XML

<storages>
    <storage id="storage0">
        <repositories>
            <repository id="repository1" policy="policy1"/>
            <repository id="repository2" policy="policy2"/>
        </repositories>
    </storage>
    <storage id="storage1">
        <repositories>
            <repository id="repository3" />
            <repository id="repository4" />
        </repositories>
    </storage>
</storages>

基于上面的XML,为了让我的代码使用JAXB读/写XML,我还需要做些什么?据我了解,我需要使用XmlAdapter,但我不太确定如何将其应用于此案例。

1 个答案:

答案 0 :(得分:2)

以下内容:

@XmlRootElement(name = "datacenter")
public class DataCenter {
    /**
     * K: storageId V: storage
     */
    @XmlElement(name = "storages")
    @XmlJavaTypeAdapter(StorageMapAdapter.class)
    private final Map<String, Storage> storages = new LinkedHashMap<String, Storage>();
}

@XmlJavaTypeAdapter(StorageMapAdapter.class)
@XmlAccessorType(XmlAccessType.FIELD)
public class Storage {

    @XmlAttribute(name = "id")
    private String id;

    /**
     * K: repository.id V: Repository
     */
    @XmlElement(name = "repositories")
    @XmlJavaTypeAdapter(RepositoryMapAdapter.class)
    private final Map<String, Repository> repositories = new LinkedHashMap<String, Repository>();

}

public class StorageMap {
    @XmlElement(name = "storage")
    List<Storage> entries = new ArrayList<Storage>();

    public List<Storage> getEntries() {
        return entries;
    }
}

public class StorageMapAdapter extends XmlAdapter<StorageMap, Map<String, Storage>> {

    @Override
    public StorageMap marshal(Map<String, Storage> map) throws Exception {
        StorageMap storageMap = new StorageMap();
        for (Map.Entry<String, Storage> entry : map.entrySet()) {
            storageMap.getEntries().add(entry.getValue());
        }
        return storageMap;
    }

    @Override
    public Map<String, Storage> unmarshal(StorageMap storageMap) throws Exception {
        List<Storage> adaptedEntries = storageMap.entries;
        Map<String, Storage> map = new LinkedHashMap<String, Storage>(adaptedEntries.size());
        for (Storage storage : adaptedEntries) {
            map.put(storage.getId(), storage);
        }
        return map;
    }
}

@XmlRootElement(name = "repository")
@XmlAccessorType(XmlAccessType.FIELD)
public class Repository {
    @XmlAttribute(name = "id")
    private String id;

    @XmlAttribute(name = "policy")
    private String policy;
}

public class RepositoryMap {
    @XmlElement(name = "repository")
    List<Repository> entries = new ArrayList<Repository>();

    public List<Repository> getEntries() {
        return entries;
    }
}

public class RepositoryMapAdapter extends XmlAdapter<RepositoryMap, Map<String, Repository>> {

    @Override
    public RepositoryMap marshal(Map<String, Repository> map) throws Exception {
        RepositoryMap repositoryMap = new RepositoryMap();
        for (Map.Entry<String, Repository> entry : map.entrySet()) {
            repositoryMap.getEntries().add(entry.getValue());
        }
        return repositoryMap;
    }

    @Override
    public Map<String, Repository> unmarshal(RepositoryMap repositoryMap) throws Exception {
        List<Repository> adaptedEntries = repositoryMap.entries;
        Map<String, Repository> map = new LinkedHashMap<String, Repository>(adaptedEntries.size());
        for (Repository repository : adaptedEntries) {
            System.out.println("Reading repository " + repository.getId());
            map.put(repository.getId(), repository);
        }
        return map;
    }
}

在此处运行演示:http://ideone.com/NyOGVQ 通过此处的编组更新演示:http://ideone.com/NzvRzX