簡體   English   中英

使用Jackson XmlMapper進行序列化時添加DTD

[英]Add DTD when serializing with Jackson XmlMapper

當我序列化我的POJO時,一切都按預期工作。 我得到這樣的東西:

<?xml version='1.0' encoding='UTF-8'?>
<gsafeed>
   ...
</gsafeed>

收件人(Google Search Appliance)似乎期望XML包含這樣的DTD:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE gsafeed PUBLIC "-//Google//DTD GSA Feeds//EN" "">
<gsafeed>
   ...
</gsafeed>

我該如何實現?

不幸的是,沒有其他方法可以通過簡單的方式實現這一目標。

從長遠來看可能有用的一件事是提交添加此類功能的請求-聽起來像是通過XML特定的ObjectWriter公開的合理功能。

我通常不屑於Jackson的“編寫自定義序列化程序”問題的答案,因為通常有一種更簡單,更簡潔的方法。 不幸的是,除了自定義序列化程序之外,我不知道一種更好的方法來將元數據添加到序列化輸出中。

希望有人用一個更簡單的解決方案做出響應,但這應該可以完成您試圖實現的目標。

創建一個模塊來容納自定義序列化程序

public class GsaFeedModule extends SimpleModule {
    private static final String NAME = "GsaFeedModule";

    public GsaFeedModule() {
        super(NAME);
        addSerializer(GsaFeed.class, new GsaFeedSerializer());
    }

    public static class GsaFeedSerializer extends JsonSerializer<GsaFeed> {
        @Override
        public void serialize(GsaFeed gsaFeed, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeRaw("<?xml version='1.0' encoding='UTF-8'?>");
            jsonGenerator.writeRaw("<!DOCTYPE gsafeed PUBLIC \"-//Google//DTD GSA Feeds//EN\" \"\">");
            jsonGenerator.writeStartObject();
            // write fields
            jsonGenerator.writeEndObject();
        }
    }
}

注冊模塊

XmlMapper xm = new XmlMapper();
xm.registerModule(new GsaFeedModule());

設置DTD似乎沒有一種優雅的方法。 除了實現自定義序列化程序之外,您還可以考慮重寫XmlSerializerProvider以在XML生成器初始化之后寫入DTD字符串。 這是一個例子:

public class JacksonXmlDTD {
    private static class DtdXmlSerializerProvider extends XmlSerializerProvider {
        private final String dtd;

        public DtdXmlSerializerProvider(
                final XmlSerializerProvider src,
                final SerializationConfig config,
                final SerializerFactory jsf,
                final String dtd) {
            super(src, config, jsf);
            this.dtd = dtd;
        }

        @Override
        protected void _initWithRootName(final ToXmlGenerator xgen, final QName rootName)
                throws IOException {
            super._initWithRootName(xgen, rootName);
            try {
                xgen.getStaxWriter().writeDTD(dtd);
            } catch (final XMLStreamException e) {
                StaxUtil.throwXmlAsIOException(e);
            }
        }

        @Override
        public DefaultSerializerProvider createInstance(
                final SerializationConfig config, final SerializerFactory jsf) {
            return new DtdXmlSerializerProvider(this, config, jsf, dtd);
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION);
        final String dtd = "<!DOCTYPE gsafeed PUBLIC \"-//Google//DTD GSA Feeds//EN\" \"\">";
        final DtdXmlSerializerProvider serializerProvider = new DtdXmlSerializerProvider(
                (XmlSerializerProvider) xmlMapper.getSerializerProvider(),
                xmlMapper.getSerializationConfig(),
                xmlMapper.getSerializerFactory(),
                dtd);
        xmlMapper.setSerializerProvider(serializerProvider);
        final Map<String, Object> map = new HashMap<>();
        map.put("object", "value");
        System.out.println(xmlMapper.writeValueAsString(map));
    }

}

輸出:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE gsafeed PUBLIC "-//Google//DTD GSA Feeds//EN" ""><HashMap xmlns=""><object>value</object></HashMap>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM