簡體   English   中英

使用Jackson從JAXB生成的XML中反序列化Map

[英]Deserialize a Map from JAXB generated XML using Jackson

我需要反序列化使用JAXB生成的一些XML。 由於某些合規性問題,我只需要使用Jackson進行XML解析。 嘗試反序列化具有Map的類時遇到異常

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
 at [Source: (StringReader); line: 40, column: 21] (through reference chain: FileConfig["otherConfigs"]->java.util.LinkedHashMap["entry"])

我的代碼如下:

XML檔案:

    <fileConfig>
        <whetherNotify>false</whetherNotify>
        <url>....some location....</url>
        <includes>app.log</includes>
        <fileType>...some string...</fileType>
        <otherConfigs>
            <entry>
                <key>pathType</key>
                <value>1</value>
            </entry>
        </otherConfigs>
    </fileConfig>

FileConfig.java

    public class FileConfig implements Serializable {

    protected Boolean whetherNotify = false;
    protected String url;
    protected String includes;
    protected FileType fileType;
    private Map<String, String> otherConfigs = new HashMap<String, String>();

    ....getters and setters.....
}

Main.java

public class Main {
  .
  .
  .
  .
   private static <T> T unmarshallFromXML(String xml, Class<T> parseToClass) throws IOException {
        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        xmlMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
        xmlMapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        xmlMapper.setDefaultUseWrapper(false);
        xmlMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        T parsedObject = xmlMapper.readValue(xml, parseToClass);
        return parsedObject;
    }
}

請提出一種使用Jackson來成功解析該地圖的方法。

默認情況下, Map在以下位置序列化為XML

...
<key>value</key>
<key1>value1</key1>
...

格式。 沒有entry元素。 您有兩種選擇:

  1. 更改模型,而不使用Map使用List<Entry>類型。
  2. Map類型實現自定義反序列化器。

新模型

您需要創建Entry類:

class Entry {
    private String key;
    private String value;

    // getters, setters, toString
}

並將FileConfig類中的屬性更改為:

List<Entry> otherConfigs;

自定義地圖解串器

請參見以下示例:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class XmlApp {

  public static void main(String[] args) throws Exception {
    File xmlFile = new File("./test.xml");


    XmlMapper xmlMapper = new XmlMapper();

    FileConfig fileConfig = xmlMapper.readValue(xmlFile, FileConfig.class);
    System.out.println(fileConfig);
  }
}

class MapEntryDeserializer extends JsonDeserializer<Map<String, String>> {

    @Override
    public Map<String, String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Map<String, String> map = new HashMap<>();

        JsonToken token;
        while ((token = p.nextToken()) != null) {
            if (token == JsonToken.FIELD_NAME) {
                if (p.getCurrentName().equals("entry")) {
                    p.nextToken();
                    JsonNode node = p.readValueAsTree();
                    map.put(node.get("key").asText(), node.get("value").asText());
                }
            }
        }
        return map;
    }
}

class FileConfig {

  protected Boolean whetherNotify = false;
  protected String url;
  protected String includes;

  @JsonDeserialize(using = MapEntryDeserializer.class)
  private Map<String, String> otherConfigs;

  // getters, setters, toString
}

上面的代碼打印:

FileConfig{whetherNotify=false, url='....some location....', includes='app.log', otherConfigs={pathType1=2, pathType=1}}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM