使用Jackson将XML转换为Map,键应该是小写的。

3

我正在尝试将XML字符串转换为Map,下面的代码可以很好地进行转换,但是我希望Map键以统一的方式(小写或大写)呈现。

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

实际输出是:

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

期望输出是:

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

依赖项:

<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>

如果您将映射到具有命名成员的POJO,则NamingStrategy应该起作用。看起来对于使用容器有一些特殊处理。针对您的用例,请尝试实现自定义NamingStrategy(扩展PropertyNamingStrategy),强制使用小写名称。 - Marc Stroebel
不,我只需要映射,不会使用POJO。 - Rajesh Narravula
我的回应是动态的。 - Rajesh Narravula
1个回答

0

可能有更简单的方法来实现,但如果没有其他办法,您总是可以创建一个JsonDeserializer。无论如何,我认为PropertyNamingStrategy与如何将bean字段映射到xml/json相关,而不是与Map键相关,但我可能错了。请参见以下内容:

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

你需要使用JacksonXmlModule进行注册,如下所示:
@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);
}

这应该会打印出来:

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


但是它正在创建另一个问题,<Find Status=\"Success\"><Result><Provider><lastUpdated>1545391251168</lastUpdated><connection><entityType>CIMHTTPGETRequest</entityType><entityId>M7IH6HVWAAAAU74VJ5F5PBJZ</entityId></connection><connection><entityType>CIMHTTPGETRequest</entityType><entityId>M7IH6HWBAAAAU74VJ7KW72FB</entityId></connection><connection><entityType>CIMHTTPGETRequest</entityType><entityId>M7IH6HWCAAAAU74VJ4TQATY4</entityId></connection></Provider></Result></Find> <connection> 没有转换为列表。 - Rajesh Narravula
上面的XML转换映射是:{result={provider={lastupdated=1545391251168, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HVWAAAAU74VJ5F5PBJZ, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HWBAAAAU74VJ7KW72FB, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HWCAAAAU74VJ4TQATY4}}}}}, status=Success}。这是错误的格式。我正在使用另一个解析器进行列表引用,请参考链接 - Rajesh Narravula
@RajeshNarravula 我稍后会看一下。这个可能有点棘手,因为Collection类型在Pojos中是通过注解显式配置的,所以如果没有Pojos,甚至可能不可能实现。 - pirho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接