我需要反序列化使用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;
}
}
请提出一种使用杰克逊成功解析该地图的方法。
答案 0 :(得分:0)
默认情况下,Map
在以下位置被序列化为XML
:
...
<key>value</key>
<key1>value1</key1>
...
格式。没有entry
元素。您有两种选择:
Map
使用List<Entry>
类型。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}}