I am using jackson-dataformat-xml (2.9) to parse an XML into JsonNode and then parse it to JSON (the XML is very dynamic so that is why I am using JsonNode instead of binding to a POJO. e.g 'elementName' and 'id' names may vary).
It happens that during the JSON parsing phase, one of the element keys is empty string ("").
XML:
<elementName>
      <id type="pid">abcdef123</id>
</elementName>
Parsing logic:
public Parser() {
        ObjectMapper jsonMapper = new ObjectMapper();
        XmlMapper xmlMapper = new XmlMapper(new XmlFactory(new WstxInputFactory()));
}
public InputStream parseXmlResponse(InputStream xmlStream) {
        InputStream stream = null;
        try {
            JsonNode node = xmlMapper.readTree(xmlStream);
            stream = new ByteArrayInputStream(jsonMapper.writer().writeValueAsBytes(node));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stream;
    }
Json:
Result:
{
   "elementName": {
     "id": {
        "type": "pid",
        "": "abcdef123"
     }
   },
}
Expected:
{
   "elementName": {
     "id": {
        "type": "pid",
        "value": "abcdef123"
     }
   },
}
My idea is to find whenever I have the empty key "" and replace it with "value". Either at XML de-serialization or during JSON serialization. I have tried to use default serializer, filter, but haven't got it working in a nice and concise way.
Suggestions are much appreciated.
Thank you for the help.
Possible Solution:
Based on @shoek suggestion I decided to write a custom serializer to avoid creating an intermediate object (ObjectNode) during the process.
edit: refactor based on the same solution proposed by @shoek.
public class CustomNode {
    private JsonNode jsonNode;
    public CustomNode(JsonNode jsonNode) {
        this.jsonNode = jsonNode;
    }
    public JsonNode getJsonNode() {
        return jsonNode;
    }
}
public class CustomObjectsResponseSerializer extends StdSerializer<CustomNode> {
    protected CustomObjectsResponseSerializer() {
        super(CustomNode.class);
    }
    @Override
    public void serialize(CustomNode node, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        convertObjectNode(node.getJsonNode(), jgen, provider);
    }
    private void convertObjectNode(JsonNode node, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        jgen.writeStartObject();
        for (Iterator<String> it = node.fieldNames(); it.hasNext(); ) {
            String childName = it.next();
            JsonNode childNode = node.get(childName);
            // XML parser returns an empty string as value name. Replacing it with "value"
            if (Objects.equals("", childName)) {
                childName = "value";
            }
            if (childNode instanceof ArrayNode) {
                jgen.writeFieldName(childName);
                convertArrayNode(childNode, jgen, provider);
            } else if (childNode instanceof ObjectNode) {
                jgen.writeFieldName(childName);
                convertObjectNode(childNode, jgen, provider);
            } else {
                provider.defaultSerializeField(childName, childNode, jgen);
            }
        }
        jgen.writeEndObject();
    }
    private void convertArrayNode(JsonNode node, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        jgen.writeStartArray();
        for (Iterator<JsonNode> it = node.elements(); it.hasNext(); ) {
            JsonNode childNode = it.next();
            if (childNode instanceof ArrayNode) {
                convertArrayNode(childNode, jgen, provider);
            } else if (childNode instanceof ObjectNode) {
                convertObjectNode(childNode, jgen, provider);
            } else {
                provider.defaultSerializeValue(childNode, jgen);
            }
        }
        jgen.writeEndArray();
    }
}