2

我正在尝试使用通用 XmlJavaTypeAdapter 将一些 xml 解组为包装在 Guava 的 Optional 中的 java 对象。但是,我无法使用泛型使其正常工作。

我正在使用 eclipselink 2.5.1 / moxy

XML:

<?xml version="1.0" encoding="UTF-8"?>
<page>
    <label>Test</label>
    <description>Test</description>
</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();

}

标签.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);
    }

}

这是我使用泛型的适配器:

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;
        }  
    }

}

这不起作用,我得到一个包含在 Optional 中的 ElementNSImpl。如果我使用它确实有效:

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

在 Page.java 中。但是,我不确定如何使用属性来实现相同的效果。

使用此适配器确实有效:

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;
        }  
    }

}

请解释为什么我的通用适配器在没有“@XmlElement(name = "description", type = Label.class)" 的情况下无法工作,并请解释我如何为属性而不是元素实现相同的功能。

4

0 回答 0