【问题标题】:JAXB - Representing the root element as a list of custom typesJAXB - 将根元素表示为自定义类型列表
【发布时间】:2012-07-31 20:09:45
【问题描述】:

类似于 Stackoverflow 上提出的这个问题,using JAXB to represent a list as the root element,我也有同样的问题。尽管答案中概述的解决方案对我不起作用。

注意:我正在使用 Jackson fasterxml 库进行映射。

本质上,我正在从 API(recurly api)消耗一些 XML。 API返回的其中一条消息的根元素为列表,演示如下:

<plans type="array">
    <plan href="...">
    ...
    </plan>
    <plan href="...">
    ...
    </plan>
</plans>

我创建了以下 Java 类 + JAXB 注释来捕获上述内容:

@XmlRootElement(name = "plans")
public class Plans extends RecurlyObject {

    @XmlElement(name = "plan", type = Plan.class)
    private List<Plan> plans;

    public List<Plan> getPlans() { return this.plans; }

    public void setPlans(final List<Plan> plans) { this.plans = plans; }
    ...
}

这不起作用。我阅读的所有文档和文章都使用字符串而不是列表元素的自定义类型进行了上述演示。

运行上面会产生如下错误:

原因:com.fasterxml.jackson.databind.JsonMappingException:无法实例化值
来自 JSON 字符串的 [简单类型,com.ning.billing.recurly.model.Plan 类] 类型;不 单字符串构造函数/工厂方法(通过引用链: com.ning.billing.recurly.model.Plans["plan"])

我也尝试了以下方法 - 但产生了类似的问题:

@XmlRootElement(name = "plans")
public class Plans extends RecurlyObject {
    @XmlTransient
    public static final String PLANS_RESOURCE = "/plans";

    @XmlElementWrapper(name = "plans")
    @XmlElement(name = "plan", type = Plan.class)
    private List<Plan> plans;

    public List<Plan> getPlans() { return this.plans; }

    public void setPlans(final List<Plan> plans) { this.plans = plans; }
    ...
}

唯一能让我不出错的方法是在我的 Plan 类上创建一个接受 String 的 ctor。但是我的List&lt;Plan&gt; 是一个计划对象列表,所有计划的每个子节点都有一个:(

顺便说一句 - Plan Java 类工作正常 - 我用它来接收来自其他 API 调用的单个 Plan 消息。

那么,有什么想法可以使用 JAXB 将根元素(字符串以外的事物列表)正确映射到 Java 对象中吗?

干杯

更新

以下解决方案由 Pierre 在 stackoverflow 之外提供。

有可能让它与杰克逊一起工作,请参阅以下代码:

@XmlRootElement(name = "plans")
public class Plans extends RecurlyObjects<Plan> {
}

需要注意的重要细节是extends RecurlyObjects&lt;Plan&gt;RecurlyObjects 本质上是一个ArrayList

@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class RecurlyObjects<T extends RecurlyObject> extends ArrayList<T> {
}

现在可以正常使用了。

【问题讨论】:

    标签: jaxb


    【解决方案1】:

    默认情况下,您应该对属性进行注释。我已尽可能简化了您的映射。

    package forum11748159;
    
    import java.util.List;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    public class Plans extends RecurlyObject {
    
        private List<Plan> plans;
    
        @XmlElement(name = "plan")
        public List<Plan> getPlans() { return this.plans; }
    
        public void setPlans(final List<Plan> plans) { this.plans = plans; }
    
    }
    

    如果你想注释字段,你需要将@XmlAccessorType(XmlAccessType.FIELD)注释添加到你的类中:

    package forum11748159;
    
    import java.util.List;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement(name = "plans")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Plans extends RecurlyObject {
    
        @XmlElement(name = "plan")
        private List<Plan> plans;
    
        public List<Plan> getPlans() { return this.plans; }
    
        public void setPlans(final List<Plan> plans) { this.plans = plans; }
    
    }
    

    注意:我正在使用 Jackson fasterxml 库进行映射。

    Jackson 提供了对 JAXB 注释的一些支持,但据我所知,这不是一个符合 JAXB (JSR-222) 的实现。不保证按照规范解释 JAXB 注释。

    【讨论】:

    • 嗨 Blaise - 我自己刚刚得出结论,这与使用 Jackson 有关。如果我使用 Jersey 客户端进行映射,我可以让它工作。我尝试了您的建议,但得到了相同的结果。我接受这个作为答案,因为你已经强调了我们如何使用 Jackson 的可能真正的问题。干杯
    猜你喜欢
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    相关资源
    最近更新 更多