杰克逊与JAXB - 抽象类型实例化

时间:2012-09-12 11:10:19

标签: json jaxb jackson

我使用JAXB注释面临Jackson的ObjectMapper问题。具体来说,我有接口通用信息的集合,虽然我可以从XML反序列化输入,但Jackson(使用JAXB introspector)是不可能的。也许我只是缺少一些配置属性或JAXB注释?问题是“抽象类型只能使用其他类型信息进行实例化”,我认为带有类型信息的@XmlElementRef(或@XmlElement)将处理这个问题,但显而易见它没有。

请注意,如果可能,我希望仅使用JAXB注释。 例如。使用@JsonTypeInfo或@JsonDeserialize将是最后一件事。

IEntry.java:

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

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

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

感谢所有回复

2 个答案:

答案 0 :(得分:2)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。

我不确定Jackson是否支持此用例,但您似乎错误地使用了@XmlElementRef。使用@XmlElementRef时,与该类关联的根元素名称用于确定要实例化的实例。如果您的示例中节点entries@XmlRootElement(name="entry")注释不匹配。

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

选项1 - 更改@XMLRootElement上的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;
    }
}

了解更多信息

答案 1 :(得分:1)

import org.codehaus.jackson.map.annotate.JsonDeserialize;  

@JsonDeserialize(as = Entry.class)
public interface IEntry {
   String getValue();
}