Java JAXB中的自定义序列化

Java JAXB中的自定义序列化,java,xml,xml-serialization,jaxb,Java,Xml,Xml Serialization,Jaxb,有没有办法在JAXB中自定义XML序列化,就像在.NET中使用IXmlSerializable一样?i、 e.使用相当于XmlReader/Writer的程序直接控制对象序列化的能力 我已经看了XmlAdapter和@XmlJavaTypeAdapter,但它们似乎只是用来在可序列化表单之间转换类型,而这并不是我想要的 更新:特别是,我想自定义根对象的反序列化,它以编程的方式确定如何反序列化内部XML,例如使用一组特定的已知类型创建jaxb解组器 更新:我已经找到了一种解决问题的方法,但这是一个

有没有办法在JAXB中自定义XML序列化,就像在.NET中使用IXmlSerializable一样?i、 e.使用相当于XmlReader/Writer的程序直接控制对象序列化的能力

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

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


更新:我已经找到了一种解决问题的方法,但这是一个非常糟糕的黑客行为,我可能会使用其他海报建议的解决方案。

我不确定我是否完全理解您的目标,但也许您可以在根对象的无参数构造函数中以编程方式完成您想做的事情,解封对象时,将调用它来实例化该对象。

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

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

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

考虑这一点:


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

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

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

考虑这一点:


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

好的,所以我成功地实现了这一点,尽管这是一个非常糟糕的解决方案,我想我会找到一种更高级别的方法来解决这个问题,正如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); 
    }
}

好的,所以我设法让它工作了,尽管这是一个非常糟糕的解决方案,我想我会找到一个更高层次的方法来解决这个问题,正如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); 
    }
}

您能提供一些关于如何自定义序列化的更多信息吗?例如,您不希望XML标记名与字段名相同。能否提供有关如何自定义序列化的更多信息?例如,您不希望XML标记名与字段名相同,而是将我的问题一针见血。肯定同意XSD,但我还没有将其标记为已接受,因为我认为可能有一种方法可以通过使用XmlAdapters来解决我的问题。等着瞧吧……你把我的问题当场解决了。肯定同意XSD,但我还没有将其标记为已接受,因为我认为可能有一种方法可以通过使用XmlAdapters来解决我的问题。我们拭目以待。。。