Пользовательская сериализация в JAXB - PullRequest
0 голосов
/ 04 февраля 2009

Есть ли способ настроить сериализацию XML в JAXB так же, как это возможно при использовании IXmlSerializable в .NET? (то есть возможность прямого управления сериализацией объекта с использованием эквивалента XmlReader / Writer).

Я взглянул на XmlAdapter и @XmlJavaTypeAdapter, но, похоже, они просто используются для преобразования типов в сериализуемые формы и из них, что не совсем то, что я хочу.

Обновление: в частности, я бы хотел настроить десериализацию корневого объекта, который программно определяет, как именно десериализовать внутренний XML (например, создать unmarshaller jaxb с определенным набором известных типов).

Обновление: я нашел способ решить проблему, но это такой неприятный взлом, я, вероятно, пойду с одним из решений, предложенных другими авторами.

Ответы [ 3 ]

4 голосов
/ 09 февраля 2009

ОК, так что мне удалось заставить это работать, хотя это настолько неприятное решение, что, я думаю, я найду способ решения проблемы более высокого уровня, как упомянули Фабиан и Бассеро. Идея следующего кода заключается в создании универсальной сериализуемой ссылки на данные, которые вы хотите сериализовать, которая поддерживает адаптер 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); 
    }
}
1 голос
/ 09 февраля 2009

Звучит так, будто вы хотите, чтобы корневой узел содержал два разных набора узлов / деревьев xml на основе какого-либо атрибута или знаний, полученных от самого корневого узла.

Я склонен использовать JAXB, сначала создав схему (xsd), а затем сгенерировав исходный код Java, который я НИКОГДА не изменяю. Я только изменяю схему и регенерирую. Я понял, что JAXB нельзя использовать по-другому, аннотируя источник, но я не могу так говорить, так как не использую его. Если вы, вы схема ... читать на

Учтите это: http://www.w3schools.com/Schema/schema_complex_indicators.asp

Вместо того, чтобы переключать unmarshaller, просто включите оба определения xml. Они будут проанализированы независимо, и вы можете изменять поток управления программой с помощью любого атрибута, который вы бы проверили на корневом узле.

1 голос
/ 09 февраля 2009

Я не уверен, что полностью понимаю, какова ваша цель, но, возможно, вы могли бы делать то, что вы хотите сделать программно, внутри конструктора no-args вашего корневого объекта, который будет вызываться для создания экземпляра объекта, когда он не распакован .

...