2013-09-19 2 views
3

У меня есть следующий объект JavaКак обернуть раздел XML в теге CDATA с помощью Джексона

class MyXmlObject{ 
    @JsonProperty 
    private InnerObject innerObject; 
    @JsonProperty 
    private String someOtherProperty; 
} 

Когда я сериализации это с помощью

public String getXmlObjectAsXML(MyXmlObject myXmlObject){ 
    JacksonXmlModule module = new JacksonXmlModule(); 

    module.setDefaultUseWrapper(false); 
    XmlMapper mapper = new XmlMapper(module); 

    mapper.configure(SerializationFeature.INDENT_OUTPUT, true); 

    String response = ""; 

    response = mapper.writeValueAsString(myXmlObject); 
    return response; 
} 

Я хотел бы класс InnerObject быть завернутый в тег CDATA.

Каков правильный способ справиться с этим сценарием?

ответ

3

У нас был аналогичный прецедент. Нам понадобилось все поля в нашем XML, обернутом в CDATA. Это было требование API, который нам нужно было реализовать, и мы не имели права говорить в API.

Чтобы решить эту проблему, мы создали реализацию @ StaxMan-х внушения, чтобы переопределить XMLOutputFactory и XMLStreamWriter угнать writeCharacters() и позвонить writeCData() вместо этого, и это, кажется, отлично работает. Вы можете увидеть суть нашего точного кода (с именами пакетов изменены) здесь:

https://gist.github.com/jbcpollak/8312151

Короче говоря, мы создали CDataXmlOutputFactoryImpl класс, который создает CDataXmlStreamWriter. К сожалению, вместо использования наследования нам нужно было обернуть целевые классы, потому что оба они были окончательными. Кроме того, точный писатель для использования является переменным, поэтому упаковка является более безопасным вариантом.

На заводе, в дополнении к оборачивать все другие методы с чистыми функциями сквозных, вам нужно что-то вроде этого для каждой функции createXMLStreamWriter() (есть 4):

public XMLStreamWriter createXMLStreamWriter(Writer w) 
    throws XMLStreamException 
{ 

    return new CDataXmlStreamWriter(f.createXMLStreamWriter(w)); 
} 

где f - OutputFactoryImpl, построенный в классе.

В CDataXmlStreamWriter все необходимые функции чистые делегаты методов в ш, для двух методов ниже, за исключением:

public void writeCharacters(char[] text, int start, int len) 
    throws XMLStreamException 
{ 
    w.writeCharacters(text, start, len); 
} 

// All this code just to override this method 
public void writeCharacters(String text) throws XMLStreamException 
{ 

    w.writeCData(text); 
} 

Вот все, что вам нужно сделать. Просто используйте свою новую фабрику следующим образом:

Полный код можно увидеть в Gist выше.

Я не уверен, что это решение будет работать, если вам понадобится только несколько полей, завернутых в CDATA. Для этого я думаю, вам нужно будет изменить ToXmlGenerator, чтобы каким-то образом узнать о вашей модели (используя аннотации, возможно?), А затем генератор будет звонить writeCData() там, где это необходимо.

+2

все сложнее, чем я надеялся, но намного чище, чем мой взлом реального физического текста. – AnthonyJClink

+1

Согласен, я хочу, чтобы код Джексона был немного более гибким. Поскольку они обеспечивают возможность переопределять фабричные классы, я не понимаю, почему все соответствующие классы являются окончательными. Было бы еще лучше, если бы CData поддерживался аннотациями. – JBCP

2

Мне неизвестно какой-либо вариант, чтобы использовать выходные секции CDATA.

Но зачем вам нужно использовать разделы CDATA? В XML CDATA не семантически отличается от обычного текстового раздела. Он доступен только для удобства редактирования вручную.

+0

Наш esb требует этого ... Я лично никогда этого не сделаю. – AnthonyJClink

+0

Хорошо. Не уверен, как это можно было бы сделать - теоретически вы могли бы подкласса 'XMLOutputFactory', чтобы создавать экземпляры' XMLStreamWriter', которые hi-jacks 'writeCharacters()', вместо этого называет 'writeCData'. Woodstox имеет некоторые функции, помогающие делегировать вызовы, которые могут работать. Но я не могу придумать функцию по умолчанию; есть обратный («выводить весь текст как ХАРАКТЕРЫ, даже если ему поручено использовать CDATA»). – StaxMan

+0

Ох - вы также можете подать запрос на эту функцию для модуля Jackson XML. Реализация этого на самом деле будет довольно простой; вызывая 'writeCData()' вместо 'writeCharacters()'. До тех пор, пока будет хорошо использовать это для всех текстовых записей. – StaxMan

0

Я закончил тем, что просто положил местозаполнитель, пробрав оба предмета, а затем манипулировал струнами вручную ... не чистым не красивым, но он работал.

6

Существует @JacksonXmlCData начиная с версии 2.5.https://github.com/FasterXML/jackson-dataformat-xml:

@JacksonXmlCData позволяет указать, что значение свойства должно быть сериализовать в теге CDATA.

+0

wow Мне больше не нужно это делать, но его действительно приятно знать – AnthonyJClink

Смежные вопросы