Using generic @XmlJavaTypeAdapter to unmarshal wrapped in Guava's Optional

牧云@^-^@ 提交于 2019-12-09 20:19:41

问题


I'm trying to unmarshal some xml into java objects wrapped in Guava's Optional using a generic XmlJavaTypeAdapter. However, I can't get it to work properly using generics.

I'm using eclipselink 2.5.1 / moxy

XML:

<?xml version="1.0" encoding="UTF-8"?>
<page>
    <label>Test</label>
    <description>Test</description>
</page>

Page.java:

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.eclipse.persistence.oxm.annotations.XmlPath;

import com.google.common.base.Optional;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement()
public class Page {

    @XmlPath("label")
    private Label label;

    @XmlJavaTypeAdapter(OptionalLabelAdapter.class)
    private Optional<Label> description = Optional.absent();

}

Label.java:

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlValue;

@XmlAccessorType(XmlAccessType.FIELD)
public class Label {
    @XmlValue
    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

}

MoxyTest.java:

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class MoxyTest {

    public static void main(String[] args) throws JAXBException {   
        String name = "test";

        JAXBContext jc = JAXBContext.newInstance(Page.class);
        System.out.println(jc.getClass());

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Page page = (Page) unmarshaller.unmarshal(new File("xml/" + name + ".xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(page, System.out);
    }

}

This is my adapter using generics:

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

import com.google.common.base.Optional;

public class OptionalAdapter<T> extends XmlAdapter<T, Optional<T>> {

    @Override
    public Optional<T> unmarshal(T value) throws Exception {
        return Optional.of(value);
    }

    @Override
    public T marshal(final Optional<T> value) throws Exception {
        if(value.isPresent()){
            return value.get();
        } else {
            return null;
        }  
    }

}

This doesn't work, I get a ElementNSImpl wrapped in an Optional. It does work if I use:

@XmlJavaTypeAdapter(OptionalAdapter.class)
@XmlElement(name = "description", type = Label.class)
private Optional<Label> description;

in Page.java. However, I'm not sure how to achieve the same with attributes.

Using this adapter does work:

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

import com.google.common.base.Optional;

public class OptionalLabelAdapter extends XmlAdapter<Label, Optional<Label>> {

    @Override
    public Optional<Label> unmarshal(final Label value) throws Exception {
        return Optional.of(value);
    }

    @Override
    public Label marshal(final Optional<Label> value) throws Exception {
        if(value.isPresent()){
            return value.get();
        } else {
            return null;
        }  
    }

}

Please explain why my generic adapter doesn't work without "@XmlElement(name = "description", type = Label.class)" and please explain how I achieve the same for attributes instead of elements.

来源:https://stackoverflow.com/questions/19360139/using-generic-xmljavatypeadapter-to-unmarshal-wrapped-in-guavas-optional

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!