JAXB 中的自定义序列化

And*_*ndy 1 java xml jaxb xml-serialization

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

我查看了 XmlAdapter 和 @XmlJavaTypeAdapter,但它们似乎只是用于在类型与可序列化形式之间进行转换,这并不是我想要的。

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

更新:我找到了解决问题的方法,但这是一个令人讨厌的黑客攻击,我可能会采用其他海报建议的解决方案之一。

And*_*ndy 6

好的,所以我设法让这个工作,尽管这是一个令人讨厌的解决方案,我想我会找到一个更高层次的方法来解决这个问题,正如 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); 
    }
}
Run Code Online (Sandbox Code Playgroud)