如何使用Jackson将一段xml包装在CDATA标签中

时间:2013-09-19 18:18:10

标签: java xml-serialization jackson

我有以下java对象

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标记中。

处理这种情况的正确方法是什么?

4 个答案:

答案 0 :(得分:8)

自2.5以来@JacksonXmlCDatahttps://github.com/FasterXML/jackson-dataformat-xml

  

@JacksonXmlCData允许指定在CData标记内序列化属性的值。

答案 1 :(得分:3)

我们有类似的用例。我们需要在包含在CDATA中的XML中的所有文本字段。这是我们需要实现的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中,所有必要的函数都是w中方法的纯委托,除了以下两种方法:

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);
}

这就是你需要做的一切。只需使用这样的新工厂:

public void init() {
    XmlFactory factory = new XmlFactory(new InputFactoryImpl(),
            new CDataXmlOutputFactoryImpl());
    xmlMapper = new XmlMapper(factory);
    xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
}

完整的代码可以在上面的要点中看到。

如果您只需要CDATA包含的几个字段,我不确定此解决方案是否有效。为此,我认为你需要修改ToXmlGenerator,让它以某种方式知道你的模型(或许使用注释?)然后生成器会在必要时调用writeCData()

答案 2 :(得分:2)

我不知道有任何选项让输出使用CDATA部分。

但是为什么你需要使用CDATA部分?在XML中,CDATA与常规文本部分在语义上没有区别。它仅作为手动编辑的便利而存在。

答案 3 :(得分:0)

我最后只是放入一个占位符,将两个对象拼凑起来,然后手工操作字符串......不干净不漂亮但是有效。