代码之家  ›  专栏  ›  技术社区  ›  Andy

JAXB中的自定义序列化

  •  0
  • Andy  · 技术社区  · 17 年前

    有没有办法在JAXB中自定义XML序列化,就像在.NET中使用IXmlSerializable一样?(即使用XmlReader/Writer的等价物直接控制对象序列化的能力)。

    我已经看了XmlAdapter和@XmlJavaTypeAdapter,但它们似乎只是用来在可序列化表单之间转换类型,而这并不是我想要的。

    更新:特别是,我想定制根对象的反序列化,它以编程的方式确定如何反序列化内部XML(例如,使用一组特定的已知类型创建jaxb解组器)。

    更新:我已经找到了解决问题的方法,但这是一个非常讨厌的黑客行为,我可能会选择其他海报建议的解决方案之一。

    3 回复  |  直到 17 年前
        1
  •  6
  •   Andy    17 年前

    好的,所以我设法让它工作了,尽管这是一个非常糟糕的解决方案,我想我会找到一个更高层次的方法来解决这个问题,正如Fabian和basszero所提到的。下面代码的思想是为要序列化的数据创建一个通用的可序列化引用,该引用维护一个JAXB java类型适配器以编程方式执行序列化,以及一个存储结果XML的字符串字段。

    注:代码已大大简化,便于显示。。。

    // Create an instance of this class, to wrap up whatever you want to custom-serialize
    @XmlRootElement
    public static class SRef
    {
        public SRef() { }
        public SRef(Object ref)
        {
            this.ref = ref;
        }
    
        @XmlJavaTypeAdapter(SRefAdapter.class)
        public Object ref;
    }
    
    // This is the adapted class that is actually serialized 
    public static class SRefData
    {
        // This is a hint field to inform the adapter how to deserialize the xmlData
        @XmlAttribute
        public String hint;
    
        // This contains the custom-serialized object
        @XmlElement
        public String xmlData;
    }
    
        // Converts an object to and from XML using a custom serialization routine
    public static class SRefAdapter extends XmlAdapter<SRefData, Object>
    {
        @Override
        public SRefData marshal(Object value) throws Exception
        {
            if (value instanceof MyType)
            {
                SRefData data = new SRefData();
                data.xmlData = doSomeSpecificSerialization(value);
                data.hint = "myType";
                return data;
            }
            throw new IllegalArgumentException("Can't serialize unknown object type " + value.getClass());
        }
    
        @Override
        public Object unmarshal(SRefData refData) throws Exception
        {
            if (refData.hint.equals("myType"))
            {
                return doSomeSpecificDeserialization(refData.xmlData);
            }
            throw new IllegalArgumentException("Unhandled hint value in SRefData: " + refData.hint); 
        }
    }
    
        2
  •  1
  •   Fabian Steeg    17 年前

    我不确定我是否完全理解您的目标是什么,但也许您可以在根对象的no-args构造函数中以编程方式执行您想要执行的操作,当对象被解组时,该构造函数将被调用以实例化对象。

        3
  •  1
  •   basszero    17 年前

    听起来您希望根节点包含两组不同的xml节点/树,它们基于从根节点本身获得的某种属性或知识。

    我倾向于使用JAXB,首先创建一个模式(xsd),然后生成Java源代码,我从不修改它。我只修改模式和重新生成。我意识到JAXB不能以另一种方式使用,通过注释source,buy,我不能这样说,因为我不使用它。如果你想要一个模式。。。读下去

    http://www.w3schools.com/Schema/schema_complex_indicators.asp

    与其切换解组器,不如同时包含两个xml定义。它们将被解析,并且您可以通过在根节点上检查的任何属性来改变您的程序控制流。