[英]jackson xml deserialize inline array
如何反序列化這種奇怪的 XML。 在我看來,缺少道具實體(圍繞道具),但我無法更改此 XML(Web 服務)的來源。
<parents>
<parent name="first">
<description><![CDATA[Description for the first-Entity]]></description>
<prop name="level">
<value><![CDATA[1]]></value>
</prop>
<prop name="enabled">
<value><![CDATA[true]]></value>
</prop>
<prop name="version">
<value><![CDATA[1.0-beta3]]></value>
</prop>
</parent>
<parent name="second">...</parent>
...
</parents>
我的實體是
public class Test {
@Test
public void deserializerTest() throws JsonParseException, JsonMappingException, IOException {
ObjectMapper om = new XmlMapper();
List<Parent> xml = om.readValue(new File("./test.xml"),
new TypeReference<List<Parent>>() {});
}
}
public class Prop {
@JacksonXmlProperty(isAttribute = true)
public String name;
@JacksonXmlText
public String value;
}
@JacksonXmlRootElement
public class Parent {
@JacksonXmlProperty(isAttribute = true)
public String name;
public String description;
// 1. alternative with List
public List<Prop> prop;
// 2. alternative with Map
@JsonDeserialize(using = PropDeser.class)
public Map<String, String> prop;
}
public static class PropDeser extends JsonDeserializer<Map<String, String>> {
@Override
public Map<String, String> deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException,
JsonProcessingException {
Map<String, String> ret = new HashMap<String, String>();
boolean eof = false;
while (jp.hasCurrentToken()) {
JsonToken t = jp.getCurrentToken();
switch (t) {
case END_OBJECT:
if (eof) {
return ret;
}
eof = true;
break;
case VALUE_STRING:
ret.put(jp.getCurrentName(), jp.getText());
break;
default:
eof = false;
break;
}
jp.nextValue();
}
return null;
}
}
創建一個異常“無法從 JSON 字符串實例化 [簡單類型,類 my.test.Prop] 類型的值; 沒有單字符串構造函數/工廠方法(通過引用鏈:my.test.Parent["prop"])'
我不想要一個簡單的字符串列表。 我需要兩者:名稱和值。 所以我想到了通過創建自己的反序列化器來使用Map<String, String>
的想法......
錯誤似乎是方法 PropDeser.deserialize() 消耗了父項的結束標記。
java.lang.NullPointerException
at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.find(BeanPropertyMap.java:160)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:287)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:226)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:203)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2575)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1766)
at my.test.Test.deserializerTest(Test.java:57)
是否有可能在XML 流中向后迭代? 該方法如何知道何時停止? 我沒有線索。
應該可以使用 Jackson XML 模塊 2.1 和@JacksonXmlElementWrapper(useWrapping=false)
處理“解包”樣式的列表元素。
結構應該是這樣的:
@JacksonXmlRootElement(localName="parents")
public class Parents {
@JacksonXmlElementWrapper(useWrapping=false)
public List<Parent> parent;
}
public class Parent {
@JacksonXmlProperty(isAttribute=true)
public String name;
public String description;
@JacksonXmlElementWrapper(useWrapping=false)
public List<Prop> prop;
}
public class Prop {
@JacksonXmlProperty(isAttribute=true)
public String name;
public String value;
}
所以你的解決方案非常接近。
請注意,如果使用內部類,則它們需要在聲明中具有“靜態”。 我用 2.1.4 對此進行了測試,它對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.