Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Jackson XmlMapper to use data types from xml schema

I have a xml message that needs to be converted to json message format. The xml message has xml schema defined that has type information for the elements. However, the resulting json has all the values as text values instead of boolean/number as mentioned in the xml schema. How do I instruct the XmlMapper() to derive the type information from the xml schema?

XmlMapper xmlMapper = new XmlMapper();
String xmlMsg = getResourceContent("test.xml");        
JsonNode node = xmlMapper.readTree(xmlMsg.getBytes());
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);

Sample xml:

<myMessage>
     <id>333</id>
     <type>Text</type>
     <flag>true</flag>
</myMessage>

Resulting json:

{
  "id": "333",
  "type": "Text",
  "flag": "true"
}

Expected json:

{
  "id": 333,
  "type": "Text",
  "flag": true
}
like image 561
user1573133 Avatar asked Oct 24 '25 19:10

user1573133


1 Answers

If your xml schema is simple, converting "true/false" to "boolean" and "number" to "long" is enough. I have a solution.

After JsonNode node = xmlMapper.readTree(xmlMsg.getBytes());, the children of node is of type TextNode. You can travel node object, and convert TextNode to BooleanNode or LongNode if the value meet certain conditions.

Add the following method:

public static JsonNode resolveType(JsonNode jsonNode) {
    if (jsonNode instanceof ObjectNode) {
        ObjectNode objectNode = (ObjectNode) jsonNode;
        Iterator<Entry<String, JsonNode>> fields = objectNode.fields();
        while (fields.hasNext()) {
            Entry<String, JsonNode> next = fields.next();
            next.setValue(resolveType(next.getValue()));
        }
    } else if (jsonNode instanceof TextNode) {
        TextNode textNode = (TextNode) jsonNode;
        String value = textNode.textValue();
        if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) {
            jsonNode = BooleanNode.valueOf(Boolean.valueOf(value));
        } else if (StringUtils.isNumeric(value)) {
            jsonNode = LongNode.valueOf(Long.valueOf(value));
        }
    }
    return jsonNode;
}

Then use this method to resolve type of JsonNode node:

JsonNode node = xmlMapper.readTree(xmlMsg.getBytes());
node = resolveType(node); // <--- Add this statement to your code.
ObjectMapper jsonMapper = new ObjectMapper();
//...

The output should be the expected json:

{"id":333,"type":"Text","flag":true}

like image 147
Kerie Avatar answered Oct 27 '25 15:10

Kerie