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

Pom*_*pot 2 java design-patterns jaxb map

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

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

    ...
}

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

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

这个设计的目标:

  • Map给予有效使用标准(我的样品中的键),而不是搜索通过迭代上的收集搜索儿童的能力.

优点:

  • 搜索和过滤子列表的责任在对象的最近处,父对象负责检索和过滤子项,
  • Map在解组时,JAXB会自动构建它:优雅,高效,并保留Map在umarshalling(迭代)之后使用列表的后期处理构建,
  • 不同读者中的同一个对象仍然具有过滤其子女的能力,
  • 主观的,这真的是一种很好的方式:),
  • 如果@XmlJavaTypeAdapter存在的话,部分就是为了这个(网上有很多样本).

缺点(一些来自我的同事):

  • JAXB限制约束代码到具体实现而不是接口:无法Map<String, Child>在我的示例中声明(在解组时不能由JAXB实例化),
  • 也许(和我的同事的论点),它不是映射对象(根据他的简单POJO)的作用,有这样的行为,
  • @XmlJavaTypeAdapter目的只是将简单对象转换为特定类型:例如xs:dateJoda时间Calendar.

在此先感谢您的2美分.

bdo*_*han 6

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

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

  • 正如您在使用@XmlJavaTypeAdaper时从上面的示例中看到的那样,您的属性不限于Map的具体实现.
  • XmlAdapter是POJO模型的外部,因此模型没有到/来自地图行为的列表.
  • 对于任何难以映射的用例,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅