3

I'm trying convert XML string to Map, below code is converting well, but i need map keys should uniform way(Lowercase or Uppercase).

public static void main(String[] args) throws Exception {
  XmlMapper xmlMapper = new XmlMapper();
  xmlMapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
  String xml = "<Find Status=\"Success\"><Result><Provider><lastUpdated>1545391251168</lastUpdated></Provider></Result></Find>";
  System.out.println(xmlMapper.readValue(xml.getBytes(), Map.class));
} 

Actual output is:

{Status=Success, Result={Provider={lastUpdated=1545391251168}}}

Expected output is:

{status=Success, result={provider={lastupdated=1545391251168}}}

Dependencies:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.9.8</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.9.8</version>
</dependency>
Rajesh Narravula
  • 1,433
  • 3
  • 26
  • 54

1 Answers1

0

There might be easier way to do it but if nothing else works you can always create a JsonDeserializer. Anyway I think that the PropertyNamingStrategy is related how you map bean fields to xml/json not so much with Map keys but I might be wrong. See the following:

public class LowerKeyDeserializer extends JsonDeserializer<Map<String, Object>> {
    @Override
    public Map<String, Object> deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        Map<String, Object> map = new HashMap<>();
        JsonToken jsonToken;
        String name = null;
        while (null != (jsonToken = p.nextToken())) {
            switch (jsonToken) {
            case FIELD_NAME:
                name = p.getText().toLowerCase(); // "magic" here
                break;
            case VALUE_STRING:
                map.put(name, p.getText()); // value as it is
                break;
            case START_OBJECT: // and this will be a "sub"map, recursive call
                map.put(name, deserialize(p, ctxt));
                break;
            default:
                ;
            }
        }
        return map;
    }
}

You need to register above using JacksonXmlModule, see below:

@Test
public void test() throws JsonParseException, JsonMappingException, IOException {
    JacksonXmlModule xmlModule = new JacksonXmlModule();
    xmlModule.addDeserializer(Map.class, new LowerKeyDeserializer());
    XmlMapper xmlMapper = new XmlMapper(xmlModule);
    String xml = "<Find Status=\"Success\"><Result><Provider><lastUpdated>1545391251168</lastUpdated></Provider></Result></Find>";
    Map<?, ?> map = xmlMapper.readValue(xml.getBytes(), Map.class);
    System.out.println(map);
}

This should print:

{result={provider={lastupdated=1545391251168}}, status=Success}

pirho
  • 11,565
  • 12
  • 43
  • 70
  • But there is another problem it is creating, `1545391251168CIMHTTPGETRequestM7IH6HVWAAAAU74VJ5F5PBJZCIMHTTPGETRequestM7IH6HWBAAAAU74VJ7KW72FBCIMHTTPGETRequestM7IH6HWCAAAAU74VJ4TQATY4` not converting as list. – Rajesh Narravula Jan 08 '19 at 08:14
  • above xml converting map is: `{result={provider={lastupdated=1545391251168, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HVWAAAAU74VJ5F5PBJZ, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HWBAAAAU74VJ7KW72FB, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HWCAAAAU74VJ4TQATY4}}}}}, status=Success}` . this is wrong format. I'm using another Parser for List reference is [link](https://stackoverflow.com/a/52337809/1653759) – Rajesh Narravula Jan 08 '19 at 08:24
  • @RajeshNarravula I'll have a look at later. This one can be tricky one since `Collection` types are explicitly configured in Pojos with annotations so it might be even impossible withouot a Pojo. – pirho Jan 08 '19 at 08:30