3

我在使用 JAXB 注释的杰克逊的 ObjectMapper 时遇到问题。具体来说,我正在收集带有接口通用信息的集合,虽然我可以反序列化来自 XML 的输入,但对于 Jackson(使用 JAXB 内省)来说这是不可能的。也许我只是缺少一些配置属性或 JAXB 注释?问题是“抽象类型只能用额外的类型信息来实例化”,我认为带有类型信息的@XmlElementRef(或@XmlElement)可以解决这个问题,但显然它没有。

请注意,如果可能,我只想保留 JAXB 注释。例如,使用@JsonTypeInfo 或@JsonDeserialize 将是最后要做的事情。

IEntry.java:

@XmlSeeAlso(Entry.class)
public interface IEntry {
    String getValue();
}

入口.java:

@XmlRootElement(name = "entry")
public class Entry implements IEntry {

    @XmlElement(name = "value")
    String value;

    public Entry() {
    }

    public Entry(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

聚合器.java:

@XmlRootElement(name = "aggregator")
public class Aggregator {

    @XmlElementRef(type = Entry.class)
    private Set<IEntry> entries;

    public Aggregator() {
    }

    public Aggregator(Set<IEntry> entries) {
        this.entries = entries;
    }

    public Set<IEntry> getEntries() {
        return entries;
    }
}

测试方法:

@Test
    public void testSerialization() throws Exception {
        ObjectMapper om = new ObjectMapper();
        AnnotationIntrospector intr = new JaxbAnnotationIntrospector();
        om.getDeserializationConfig().withAnnotationIntrospector(intr);

        String json = "{\"entries\":[{\"value\":\"X\"},{\"value\":\"Y\"},{\"value\":\"Z\"}]}\";\n}";
        Aggregator agr = om.readValue(json, Aggregator.class);
    }

感谢所有回复

4

2 回答 2

2

注意: 我是EclipseLink JAXB (MOXy)负责人,也是JAXB (JSR-222)专家组的成员。

我不确定杰克逊是否支持这个用例,但你似乎使用@XmlElementRef不正确。当您使用@XmlElementRef与类关联的根元素名称时,用于确定要实例化的实例。如果您的示例节点与注释entries不匹配。@XmlRootElement(name="entry")

您可以尝试以下选项之一(它们都适用于 MOXy 的 JSON 绑定,请参阅: http ://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html ):

@XMLRootElement选项1 - 更改Entry

@XmlRootElement(name = "entries")
public class Entry implements IEntry {

    @XmlElement(name = "value")
    String value;

    public Entry() {
    }

    public Entry(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

选项 #2 - 更改 JSON 文档

{"entry":[{"value":"X"},{"value":"Y"},{"value":"Z"}]}}

选项 #3 - 使用@XMLElement而不是@XMLElementRef

如果您使用@XmlElement注释,您可以在字段/属性上指定节点名称应该是什么,而不是依赖@XmlRootElement注释。此外,如果您注释应该@XmlAccessorType(XmlAccessType.FIELD)在类型级别指定的字段。

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

@XmlRootElement(name = "aggregator")
@XmlAccessorType(XmlAccessType.FIELD)
public class Aggregator {

    @XmlElement(type = Entry.class)
    private Set<IEntry> entries;

    public Aggregator() {
    }

    public Aggregator(Set<IEntry> entries) {
        this.entries = entries;
    }

    public Set<IEntry> getEntries() {
        return entries;
    }
}

了解更多信息

于 2012-09-12T13:27:45.160 回答
1
import org.codehaus.jackson.map.annotate.JsonDeserialize;  

@JsonDeserialize(as = Entry.class)
public interface IEntry {
   String getValue();
}  
于 2012-09-12T12:44:15.217 回答