首页 文章

来自List的JAXB XmlJavaTypeAdapter Map:此设计模式的优缺点

提问于
浏览
2

我编写了一个JAXB映射,它将子列表存储在 LinkedHashMap<String, Object> 中的根元素内,而不是通过特定的 XmlJavaTypeAdapter 维护的 Collection<Object> . 下面是一个示例:

@XmlRootElement
public class Parent {
    @XmlJavaTypeAdapter(ListToMapAdapter.class)
    @XmlElement
    private LinkedHashMap<String, Child> children;

    ...
}

密钥是根据子标记的属性构建的(例如 <child id="key">Map.Entry<String, Child> ,如 {key => child} .

我的一个同事说它的设计很糟糕,并且这个应该在负责解组XML的对象中 . 我不同意他的看法 . 以下是这种方法的一些优点和缺点 . 您认为哪种设计最好?您认为哪些优点和缺点可以完成辩论?

Goal of this design:

  • Map 能够有效地搜索具有标准的孩子(我的样本中的关键字),而不是通过迭代搜索Collecion .

Pros:

  • 用于搜索和过滤子列表的责任在对象的最近处,父对象负责检索和过滤其子项,

  • _4448560_的构建由JAXB在解组时自动生成:优雅,高效, preserve from building the Map with a post process of the list after umarshalling (iteration)

  • 不同读者中的同一个对象仍然具有过滤其子女的能力,

  • 主观,这真的是一种很好的方式:),

  • 如果 @XmlJavaTypeAdapter 存在,部分原因是这一点(Web上的大量样本) .

Cons (有些来自我的同事) :

  • JAXB限制约束代码到具体实现而不是接口:无法在我的示例中声明 Map<String, Child> (在解组时不能由JAXB实例化),

  • 也许(和我的同事的论点),它不是映射对象(根据他的简单POJO)的角色有这样的行为,

  • @XmlJavaTypeAdapter 仅用于将简单对象转换为特定类型:例如 xs:date 到Joda time Calendar .

在此先感谢您的2美分 .

2 回答

  • 1

    我总是建议人们为他们的应用设计最好的模型 . 然后让JAXB处理将其映射到XML的难度 . 在这种情况下,如果父母有一个孩子的 Map 是有意义的,那么通过这种方式一定模仿它 . JAXB确实支持Map,但是使用您描述的XML表示法,您将需要使用XmlAdapter . 有关更多信息,请参阅

    所有优点似乎都合理 . 没有任何缺点是有效的:

    • 正如您在使用@XmlJavaTypeAdaper时从上面的示例中看到的那样,您的属性不限于Map的具体实现 .

    • XmlAdapter是POJO模型的外部,因此模型没有到/来自 Map 行为的列表 .

    • XmlAdapter对于任何难以映射的用例都是一个全部捕获 . 它不仅限于简单的对象 . 常见的用例是映射Map的实例 .

    如果要消除包装元素,则可以在MOXy JAXB实现中使用@XmlPath扩展 . 我的博客文章中的Foo类将略有修改:

    import java.util.HashMap;
    import java.util.Map;
    import javax.xml.bind.annotation.*;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    import org.eclipse.persistence.oxm.annotations.XmlPath;
    
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Foo {
        @XmlJavaTypeAdapter(MyMapAdapter.class)
        @XmlPath(".")
        Map<Integer, String> map = new HashMap<Integer, String>();
    
        public Map<Integer, String> getMap() {
            return map;
        }
    
        public void setMap(Map<Integer, String> map) {
            this.map = map;
        }
    }
    

    有关更多信息,请参阅

  • 6

    感谢您的亮点 . 我现在确信我的方式是好的方式,我的同事需要修改他的观点:-) .

    我看过你的博文 . 实际上,我已成功实现与接口上的适配器解组 . 不知道为什么到目前为止我失败了 .

    仍然是一个遗留问题,我仍然没有实现映射未嵌套在元素包装器中的元素列表,如下所述:http://weblogs.java.net/blog/2005/04/22/xmladapter-jaxb-ri-ea . 像你一样,在JavaDoc中解释它,我需要在你的例子中使用一个中间包装器对象( MyMapType ) . 是否可以直接创建 XmlJavaTypeAdapter<List<WrappedObject>, Map<String, WrappedObject>> 而不是将 List 放在 ListWrapper<WrappedObject> 中?我当然会在S.O.中单独发表这个问题的帖子 . 办法 .

相关问题