【问题标题】:Convert XML to Map using Jackson, Key should be lowercase使用 Jackson 将 XML 转换为 Map,Key 应为小写
【发布时间】:2019-01-07 11:15:54
【问题描述】:

我正在尝试将 XML 字符串转换为 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));
} 

实际输出为:

{状态=成功,结果={提供者={lastUpdated=1545391251168}}}

预期输出为:

{status=成功,结果={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>

【问题讨论】:

  • NamingStrategy 如果您映射到具有命名成员的 pojo,则应该可以工作。看起来有一些使用容器的特殊处理。对于您的用例,尝试实现一个自定义 NamingStrategy(扩展 PropertyNamingStrategy),它强制使用小写名称
  • 不..我只需要地图,我不会去 pojo..
  • 我的反应是动态的。

标签: java jackson fasterxml jackson-dataformat-xml


【解决方案1】:

可能有更简单的方法,但如果没有其他方法,您可以随时创建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}},状态=成功}

【讨论】:

  • 但是它正在创建另一个问题,&lt;Find Status=\"Success\"&gt;&lt;Result&gt;&lt;Provider&gt;&lt;lastUpdated&gt;1545391251168&lt;/lastUpdated&gt;&lt;connection&gt;&lt;entityType&gt;CIMHTTPGETRequest&lt;/entityType&gt;&lt;entityId&gt;M7IH6HVWAAAAU74VJ5F5PBJZ&lt;/entityId&gt;&lt;/connection&gt;&lt;connection&gt;&lt;entityType&gt;CIMHTTPGETRequest&lt;/entityType&gt;&lt;entityId&gt;M7IH6HWBAAAAU74VJ7KW72FB&lt;/entityId&gt;&lt;/connection&gt;&lt;connection&gt;&lt;entityType&gt;CIMHTTPGETRequest&lt;/entityType&gt;&lt;entityId&gt;M7IH6HWCAAAAU74VJ4TQATY4&lt;/entityId&gt;&lt;/connection&gt;&lt;/Provider&gt;&lt;/Result&gt;&lt;/Find&gt; 没有转换为列表。
  • 以上xml转换图为:{result={provider={lastupdated=1545391251168, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HVWAAAAU74VJ5F5PBJZ, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HWBAAAAU74VJ7KW72FB, connection={entitytype=CIMHTTPGETRequest, entityid=M7IH6HWCAAAAU74VJ4TQATY4}}}}}, status=Success}。这是错误的格式。我正在使用另一个解析器作为列表参考是link
  • @RajeshNarravula 我稍后会看看。这可能是一个棘手的问题,因为 Collection 类型在 Pojos 中使用注释显式配置,因此如果没有 Pojo,它甚至是不可能的。
猜你喜欢
  • 2015-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 2015-06-28
  • 1970-01-01
相关资源
最近更新 更多