1

类似于在 Stackoverflow 上提出的这个问题,使用 JAXB 将列表表示为根元素,我有同样的问题。尽管答案中概述的解决方案对我不起作用。

注意:我正在使用 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<Plan>是一个计划对象的列表,一个用于所有计划的每个子节点:(

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

那么,任何想法如何使用 JAXB 正确地将作为字符串以外的事物列表的根元素映射到 Java 对象中?

干杯

更新

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

可以使它与杰克逊一起使用,请参见以下代码:

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

需要注意的重要细节是extends RecurlyObjects<Plan>RecurlyObjects本质上是一个ArrayList.

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

这现在工作正常。

4

1 回答 1

2

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

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 注释。

于 2012-07-31T21:01:38.500 回答