1

I try to convert a JSON into an XML with the following code

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

JsonNode jsonNode = objectMapper.readTree(jsonString);

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

Basically it works. Does anyone know, how I can add a namespace to the serialized XML-attributes. I've no POJOs for the objects. The convert should generate from this

{
    "Status" : "OK"
}

something like this:

<ns2:rootname xmlns:ns2="http://whatever-it-is.de/">
  <ns2:state>OK</ns2:state>
</ns2:rootname>
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
dank
  • 21
  • 3

3 Answers3

0

just create a pojo and add jackson annotations, e.g.

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

Or if you want to go without a pojo try a custom serializer which adds namespaces

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

Marc Stroebel
  • 2,295
  • 1
  • 12
  • 21
  • As mentioned, I cant create a POJO with annotation. I dont know the object, which I've to transform. I hopped, there is another way to set the property to the mapper. Worst case is the serializer ... – dank Aug 24 '22 at 16:03
0

You need to provide custom Json Node serialiser and use ToXmlGenerator. See below example:

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

Above example prints:

<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>
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • Thank you Michal. The code is working for my simple example. For arbitrary complex JSON to XML its not working. Already this example [link](https://www.w3schools.com/xml/xml_namespaces.asp) fails. Do I really have to manage all cases (childnodes, arrays etc) by myself or is there eventually a configuration way? – dank Aug 25 '22 at 08:55
  • @dank, take a look on the updated version. Instead of using custom serialiser we just modify existing one. First we need to provide a namespace info and use base implementation to write the object. – Michał Ziober Aug 25 '22 at 11:53
0

Underscore-java library can convert JSON to XML with namespace.

{
  "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>
Valentyn Kolesnikov
  • 2,029
  • 1
  • 24
  • 31