【问题标题】:How to dynamically convert JSON to XML with custom namespace?如何使用自定义命名空间将 JSON 动态转换为 XML?
【发布时间】:2022-10-05 14:56:58
【问题描述】:

我尝试使用以下代码将JSON 转换为XML

final ObjectMapper objectMapper = new ObjectMapper();
final XmlMapper xmlMapper = new XmlMapper();

JsonNode jsonNode = objectMapper.readTree(jsonString);

String xmlString = xmlMapper
   .writerWithDefaultPrettyPrinter()
   .withRootName(\"rootname\")
   .writeValueAsString(jsonNode);

基本上它有效。有谁知道,我如何将命名空间添加到序列化的 XML 属性中。我没有对象的 POJO。转换应该由此生成

{
    \"Status\" : \"OK\"
}

像这样的东西:

<ns2:rootname xmlns:ns2=\"http://whatever-it-is.de/\">
  <ns2:state>OK</ns2:state>
</ns2:rootname>

    标签: java json xml jackson jsonnode


    【解决方案1】:

    只需创建一个 pojo 并添加杰克逊注释,例如

    @JacksonXmlProperty(localName="ns2:http://whatever-it-is.de/")
    public class Status {
    // ...
    }
    

    或者,如果您想不使用 pojo,请尝试添加命名空间的自定义序列化程序

    https://www.baeldung.com/jackson-custom-serialization

    【讨论】:

    • 如前所述,我无法创建带有注释的 POJO。我不知道我必须转换的对象。我跳了,还有另一种方法可以将属性设置为映射器。最坏的情况是序列化器......
    【解决方案2】:

    您需要提供自定义的Json Node 序列化器并使用ToXmlGenerator。请参见下面的示例:

    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.BeanDescription;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializationConfig;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import com.fasterxml.jackson.databind.SerializerProvider;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
    import com.fasterxml.jackson.dataformat.xml.XmlMapper;
    import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
    
    import javax.xml.namespace.QName;
    import java.io.IOException;
    
    public class XmlMapperApp {
    
        public static void main(String... args) throws Exception {
            XmlMapper xmlMapper = new XmlMapper();
            xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
    
            ObjectNode node = xmlMapper.createObjectNode()
                    .put("Status", "OK")
                    .set("node", xmlMapper.createObjectNode()
                            .put("int", 1)
                            .put("str", "str"));
    
            SimpleModule module = new SimpleModule();
            module.setSerializerModifier(new BeanSerializerModifier() {
                @Override
                public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                    if (beanDesc.getType().getRawClass().equals(ObjectNode.class)) {
                        return new ObjectNodeJsonSerializer(serializer);
                    }
                    return super.modifySerializer(config, beanDesc, serializer);
                }
            });
            xmlMapper.registerModule(module);
    
            System.out.println(xmlMapper.writeValueAsString(node));
        }
    }
    
    class ObjectNodeJsonSerializer extends JsonSerializer<JsonNode> {
    
        private final JsonSerializer baseSerializer;
    
        ObjectNodeJsonSerializer(JsonSerializer baseSerializer) {
            this.baseSerializer = baseSerializer;
        }
    
        @Override
        public void serialize(JsonNode value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            ToXmlGenerator xmlGenerator = (ToXmlGenerator) gen;
    
            xmlGenerator.setNextName(new QName("http://whatever-it-is.de/", "rootname", "anything"));
            baseSerializer.serialize(value, gen, serializers);
        }
    }
    

    上面的示例打印:

    <wstxns1:rootname xmlns:wstxns1="http://whatever-it-is.de/">
      <wstxns1:Status>OK</wstxns1:Status>
      <wstxns1:node>
        <wstxns1:int>1</wstxns1:int>
        <wstxns1:str>str</wstxns1:str>
      </wstxns1:node>
    </wstxns1:rootname>
    

    【讨论】:

    • 谢谢你,迈克尔。该代码适用于我的简单示例。对于任意复杂的 JSON 到 XML,它不起作用。这个例子link 已经失败了。我真的必须自己管理所有情况(子节点、数组等)还是最终有配置方式?
    • @dank,看看更新的版本。我们只是修改现有的序列化程序,而不是使用自定义序列化程序。首先,我们需要提供命名空间信息并使用基本实现来编写对象。
    【解决方案3】:

    Underscore-java 库可以将 JSON 转换为带有命名空间的 XML。

    {
      "ns2:rootname": {
        "-xmlns:ns2": "http://whatever-it-is.de/",
        "ns2:state": "OK"
      },
      "#omit-xml-declaration": "yes"
    }
    
    <ns2:rootname xmlns:ns2="http://whatever-it-is.de/">
      <ns2:state>OK</ns2:state>
    </ns2:rootname>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-18
      • 2014-07-23
      • 2014-11-28
      • 1970-01-01
      • 2010-12-16
      • 2019-11-19
      相关资源
      最近更新 更多