How do I get Jackson's XMLMapper to read the name of the root xml element when deserializing?
I am deserializing input XML to generic Java class, LinkedHashMap and then to JSON. I want to dynamically read the root element of input XML on deserialization to LinkedHashMap.
Code
XmlMapper xmlMapper = new XmlMapper();
Map entries = xmlMapper.readValue(new File("source.xml"), LinkedHashMap.class);
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writer().writeValueAsString(entries);
System.out.println(json);
Input XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<File>
<NumLeases>1</NumLeases>
<NEDOCO>18738</NEDOCO>
<NWUNIT>0004</NWUNIT>
<FLAG>SUCCESS</FLAG>
<MESSAGE>Test Upload</MESSAGE>
<Lease>
<LeaseVersion>1</LeaseVersion>
<F1501B>
<NEDOCO>18738</NEDOCO>
<NWUNIT>0004</NWUNIT>
<NTRUSTRECORDKEY>12</NTRUSTRECORDKEY>
</F1501B>
</Lease>
</File>
Actual Output
{"NumLeases":"1","NEDOCO":"18738","NWUNIT":"0004","FLAG":"SUCCESS","MESSAGE":"Test Upload","Lease":{"LeaseVersion":"1","F1501B":{"NEDOCO":"18738","NWUNIT":"0004","NTRUSTRECORDKEY":"12"}}}
Expected Output (Note: There is a root element named "File" present in JSON)
{"File":{"NumLeases":"1","NEDOCO":"18738","NWUNIT":"0004","FLAG":"SUCCESS","MESSAGE":"Test Upload","Lease":{"LeaseVersion":"1","F1501B":{"NEDOCO":"18738","NWUNIT":"0004","NTRUSTRECORDKEY":"12"}}}}
There's probably some switch somewhere to set it. Any help shall be appreciated.
Sadly there is no flag for that. It can be done with a custom implementation of com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer
. (Jackson How-To: Custom Deserializers):
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
import java.io.File;
import java.io.IOException;
//...
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new SimpleModule().addDeserializer(JsonNode.class,
new JsonNodeDeserializer() {
@Override
public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String rootName = ((FromXmlParser)p).getStaxReader().getLocalName();
return ctxt.getNodeFactory()
.objectNode().set(rootName, super.deserialize(p, ctxt));
}
}));
JsonNode entries = xmlMapper.readTree(new File("source.xml"));
System.out.println(entries);