java jackson xml 反序列化内联数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13179920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hymanson xml deserialize inline array
提问by mailwurf
How to deserialize such strange XML. In my opinion, the props-entity is missing (around the props), but I can't change the source of this XML (a web service).
如何反序列化这种奇怪的 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>
My entities are
我的实体是
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 {
@HymansonXmlProperty(isAttribute = true)
public String name;
@HymansonXmlText
public String value;
}
@HymansonXmlRootElement
public class Parent {
@HymansonXmlProperty(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;
}
}
1. Alternative
1. 替代
creates an exception?'Can not instantiate value of type [simple type, class my.test.Prop] from JSON String; no single-String constructor/factory method (through reference chain: my.test.Parent["prop"])'
创建异常?'无法从 JSON 字符串实例化 [简单类型,类 my.test.Prop] 类型的值;没有单字符串构造函数/工厂方法(通过引用链:my.test.Parent["prop"])'
I don't want a simple-String list. I need both: name and value. So I came to the idea of using a Map<String, String>
by creating my own deserializer...
我不想要一个简单的字符串列表。我需要两个:名称和值。所以我想到了Map<String, String>
通过创建自己的反序列化器来使用 a 的想法......
2. Alternative
2. 替代
The error seems to be method PropDeser.deserialize()?consumes the closing-tag of the parent.
错误似乎是方法 PropDeser.deserialize()?consumes the结束标签。
java.lang.NullPointerException
at com.fasterxml.Hymanson.databind.deser.impl.BeanPropertyMap.find(BeanPropertyMap.java:160)
at com.fasterxml.Hymanson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:287)
at com.fasterxml.Hymanson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112)
at com.fasterxml.Hymanson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:226)
at com.fasterxml.Hymanson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:203)
at com.fasterxml.Hymanson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
at com.fasterxml.Hymanson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2575)
at com.fasterxml.Hymanson.databind.ObjectMapper.readValue(ObjectMapper.java:1766)
at my.test.Test.deserializerTest(Test.java:57)
Is there a possibility to iterate backward in the XML-stream??How can the method know when to stop? I have no clue.
是否有可能在XML 流中向后迭代?该方法如何知道何时停止?我没有任何线索。
回答by StaxMan
It should be possible to handle "unwrapped" style of list elements with Hymanson XML module 2.1, with @HymansonXmlElementWrapper(useWrapping=false)
.
应该可以使用 Hymanson XML 模块 2.1 处理“解包”样式的列表元素,使用@HymansonXmlElementWrapper(useWrapping=false)
.
Structure should be something like this:
结构应该是这样的:
@HymansonXmlRootElement(localName="parents")
public class Parents {
@HymansonXmlElementWrapper(useWrapping=false)
public List<Parent> parent;
}
public class Parent {
@HymansonXmlProperty(isAttribute=true)
public String name;
public String description;
@HymansonXmlElementWrapper(useWrapping=false)
public List<Prop> prop;
}
public class Prop {
@HymansonXmlProperty(isAttribute=true)
public String name;
public String value;
}
so your solution was quite close.
所以你的解决方案非常接近。
Note that if inner classes are used, they need to have 'static' in declaration. I tested this with 2.1.4, and it works for me.
请注意,如果使用内部类,则它们需要在声明中具有“静态”。我用 2.1.4 对此进行了测试,它对我有用。