JAXB Marshall a Map структура универсального типа - PullRequest
2 голосов
/ 30 ноября 2011

Следуя этому примеру (http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html) Блейза Дафана, который работает, я пытаюсь обобщить его для любого типа с использованием обобщений. Я получил:

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MyMapType<K, V> {

    public List<MyMapEntryType<K, V>> entry;

    public MyMapType() {
        entry = new ArrayList<MyMapEntryType<K, V>>();
    }

}

а,

import javax.xml.bind.annotation.*;

public class MyMapEntryType<K, V> {

    @XmlAttribute
    public K key;

    @XmlValue
    public V value;

}

тогда

import java.util.*;
import java.util.Map.Entry;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public final class MyMapAdapter<K, V> extends
        XmlAdapter<MyMapType<K, V>, Map<K, V>> {

    @Override
    public MyMapType<K, V> marshal(Map<K, V> arg0) throws Exception {
        MyMapType<K, V> myMapType = new MyMapType<K, V>();
        for (Entry<K, V> entry : arg0.entrySet()) {
            MyMapEntryType<K, V> myMapEntryType = new MyMapEntryType<K, V>();
            myMapEntryType.key = entry.getKey();
            myMapEntryType.value = entry.getValue();
            myMapType.entry.add(myMapEntryType);
        }
        return myMapType;
    }

    @Override
    public Map<K, V> unmarshal(MyMapType<K, V> arg0) throws Exception {
        HashMap<K, V> hashMap = new HashMap<K, V>();
        for (MyMapEntryType<K, V> myEntryType : arg0.entry) {
            hashMap.put(myEntryType.key, myEntryType.value);
        }
        return hashMap;
    }

}

наконец,

package forum832656;

import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo<K, V> {

    @XmlJavaTypeAdapter(MyMapAdapter.class)
    Map<K, V> map = new HashMap<K, V>();

    public Foo() {
    }

    public Map<K, V> getMap() {
        return map;
    }

    public void setMap(Map<K, V> map) {
        this.map = map;
    }

}

Тогда я попробовал это,

 Foo<Integer,String> f = new Foo<Integer,String>();
    f.getMap().put(1, "HELLO");
    f.getMap().put(2, "WORLD");


    JAXBContext context =   JAXBContext.newInstance(Foo.class,MyMapType.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(f, System.out);

Но я получил исключение NullPointerException в строке создания JAXBContext .... Есть идеи?

Ответы [ 2 ]

3 голосов
/ 26 июня 2013

Я решил это с помощью рекурсивного адаптера:

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class MapAdapter<K, V> extends XmlAdapter<Adapter<K, V>, Map<K, V>> {

    @Override
    public Map<K, V> unmarshal(Adapter<K, V> v) throws Exception {
        if (v == null) {
            return null;
        }
        Map<K, V> map = new HashMap<K, V>();
        for (MyEntry<K, V> mapEntryType : v.getEntries()) {
            map.put(rUnmarshal(mapEntryType.getKey()),     rUnmarshal(mapEntryType.getValue()));
        }
        return map;
    }

    @Override
    public Adapter<K, V> marshal(Map<K, V> v) throws Exception {
        if (v == null) {
            return null;
        }
        return new Adapter<K, V>(v);
    }

    @SuppressWarnings("unchecked")
    private static <T> T rUnmarshal(T obj) throws Exception {
        if (obj instanceof Adapter) {
            return (T) new MapAdapter<>().unmarshal((Adapter<Object, Object>) obj);
        }
        return obj;
    }

    @SuppressWarnings("unchecked")
    static <T> T rMarshal(T obj) throws Exception {
        if (obj instanceof Map) {
            return (T) new MapAdapter<>().marshal((Map<Object, Object>) obj);
        }
        return obj;
    }

    @XmlType
    @XmlRootElement
    public final static class Adapter<K, V> {

        @XmlElement
        protected List<MyEntry<K, V>> fEntries = new LinkedList<MyEntry<K, V>>();

        // needed for JAXB
        @SuppressWarnings("unused")
        private Adapter() {
        }

        public Adapter(Map<K, V> original) throws Exception {
            for (Map.Entry<K, V> entry : original.entrySet()) {
                this.fEntries.add(new MyEntry<K, V>(entry));
            }
        }

        public List<MyEntry<K, V>> getEntries() {
            return this.fEntries;
        }

    }

    @XmlType
    @XmlRootElement
    public final static class MyEntry<K, V> {

        @XmlElement
        protected K fKey;

        @XmlElement
        protected V fValue;

        // needed for JAXB
        @SuppressWarnings("unused")
        private MyEntry() {
        }

        public MyEntry(Map.Entry<K, V> original) throws Exception {
            this.fKey = rMarshal(original.getKey());
            this.fValue = rMarshal(original.getValue());
        }

        public K getKey() {
            return this.fKey;
        }

        public V getValue() {
            return this.fValue;
        }

    }

}

Это должно избежать вашего NPE.

0 голосов
/ 25 января 2017

Спасибо.Выше код не скомпилирован здесь, я должен был изменить его в код ниже.Мне не нравятся большие количества xsi: и xlmns: вещи в сериализованной форме.

package misc;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class MapAdapter<K, V> extends XmlAdapter<Adapter<K, V>, Map<K, V>> {

    @Override
    public Map<K, V> unmarshal(Adapter<K, V> v) throws Exception {
        if (v == null) {
            return null;
        }
        Map<K, V> map = new HashMap<K, V>();
        for (MyEntry<K, V> mapEntryType : v.getEntries()) {
            map.put(rUnmarshal(mapEntryType.getKey()), rUnmarshal(mapEntryType.getValue()));
        }
        return map;
    }

    @Override
    public Adapter<K, V> marshal(Map<K, V> v) throws Exception {
        if (v == null) {
            return null;
        }
        return new Adapter<K, V>(v);
    }

    @SuppressWarnings("unchecked")
    protected static <T> T rUnmarshal(T obj) throws Exception {
        if (obj instanceof Adapter) {
            return (T) new MapAdapter<>().unmarshal((Adapter<Object, Object>) obj);
        }
        return obj;
    }

    @SuppressWarnings("unchecked")
    protected static <T> T rMarshal(T obj) throws Exception {
        if (obj instanceof Map) {
            return (T) new MapAdapter<>().marshal((Map<Object, Object>) obj);
        }
        return obj;
    }

}

@XmlType
@XmlRootElement
final class Adapter<K, V> {

    @XmlElement
    protected List<MyEntry<K, V>> fEntries = new LinkedList<MyEntry<K, V>>();

    // needed for JAXB
    @SuppressWarnings("unused")
    private Adapter() {
    }

    public Adapter(Map<K, V> original) throws Exception {
        for (Map.Entry<K, V> entry : original.entrySet()) {
            this.fEntries.add(new MyEntry<K, V>(entry));
        }
    }

    public List<MyEntry<K, V>> getEntries() {
        return this.fEntries;
    }

}

@XmlType
@XmlRootElement
final class MyEntry<K, V> {

    @XmlElement
    protected K fKey;

    @XmlElement
    protected V fValue;

    // needed for JAXB
    @SuppressWarnings("unused")
    private MyEntry() {
    }

    public MyEntry(Map.Entry<K, V> original) throws Exception {
        this.fKey = MapAdapter.rMarshal(original.getKey());
        this.fValue = MapAdapter.rMarshal(original.getValue());
    }

    public K getKey() {
        return this.fKey;
    }

    public V getValue() {
        return this.fValue;
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...