我有以下xml
<root>
<date>112004</date>
<entries>
<entry id = 1>
<status>Active</status>
<person>
<Name>John</Name>
<Age>22</Age>
</person>
</entry>
<entry id = 2>
<status>Active</status>
<person>
<Name>Doe</Name>
<Age>32</Age>
</person>
</entry>
<entry id = 3>
<status>N/A</status>
</entry>
</entries>
我正在使用自定义jackson反序列化程序获取值,pojo看起来像
@JacksonXmlRootElement(localName="root", namespace="namespace")
类根{私有字符串日期;
@JacksonXmlProperty(localName = "entries", namespace="tns")
private List<Entry> entries;
//getter and setter
}
class Entry {
private String id;
private String status;
private Person person;
//getter and setter
}
反序列化程序代码如下所示
public class DeSerializer extends StdDeserializer<root>
{
protected DeSerializer() {
super(root.class);
}
@Override
public root deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode nodes = p.readValueAsTree();
ObjectMapper mapper = new ObjectMapper();
List<Entry> entry = mapper.convertValue(nodes.findValues("entry"), new TypeReference<List<Entry>>() {});
}
}
main()
{
XmlMapper x = new XmlMapper();
final SimpleModule module = new SimpleModule("configModule", com.fasterxml.jackson.core.Version.unknownVersion());
module.addDeserializer(root.class, new DeSerializer());
x.registerModule(module);
root r = x.readValue(xmlSource, root.class); /*xmlsource is xml as string*/
}
问题是,当我调试时,我总是从xml中获取条目的最后一个值。所以节点(在反序列化器中)的值是{“date”:“112004”,“entries”:{“entry”:{“id”:“3”,“status”:“N/A”}}}},我不知道为什么它不被视为列表。我确实为列表添加了unwrapped=false的注释,但没有成功。
如果有人仍然面临此问题,请升级到最新的jackson 2.12.3版本。我在2.11.x版本中遇到了这个问题。
我明白为什么史蒂芬·哈兹拉的答案被否决了,因为他并没有真正回答这个问题:他是对的。
我不知道确切的版本,但直到2.11. x xml中数组的自定义反序列化被破坏。如果我们从问题中获取xml并实现一个反序列化器并像这样使用它:
@JsonDeserialize(using = MyDeserializer.class)
private List<MyClass> entries = new ArrayList<>();
如果MyDeserializer类从StdSerializer扩展,也像问题中一样,反序列化方法总是只从要处理的条目的子项中获取最后一个子“条目”元素。
在以后的版本中,这是固定的,您现在可以实现反序列化方法,如下所示:
@Override
public List<MyClass> deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
final List<MyClass> result = new ArrayList<>();
final ObjectNode node = jsonParser.getCodec().readTree(jsonParser);
//entry and extendedEntry are different children in the xml that can be parsed as MyClass
processNode((ContainerNode) node.get("entry"), jsonParser, result);
processNode((ContainerNode) node.get("extendedEntry"), jsonParser, result);
return result;
}
private void processNode(ContainerNode cNode, JsonParser jsonParser, List<MyClass> result) throws IOException {
if (cNode == null) return;
//cNode can either be an ObjectNode or an ArrayNode based on how many children there can be found in the xml.
if (cNode.isArray()) { cNode.iterator().forEachRemaining(node -> {
try {
result.add(node.traverse(jsonParser.getCodec()).readValueAs(MyClass.class));
} catch (IOException e) {
//whatever
}
});
} else {
result.add(cNode.traverse(jsonParser.getCodec()).readValueAs(MyClass.class));
}
}
我把这个例子写下来作为答案,因为我基本上被困了一个下午,想知道如何处理xml中的其他子元素,因为在我的例子中,xml中的子元素具有不同的标记名,但内容类型相同,因此仅用contentUsing解析内容是不够的,因为那样我就丢失了基于孩子原始标签名的重要信息。最终,我使用的杰克逊2.11版本在这方面被破坏了。感谢Stephen为我指明了方向。
它似乎不支持获取整个集合。
我在没有自定义反序列化器的情况下做了一些工作。
@JacksonXmlRootElement(localName="root")
public class Root {
@JacksonXmlElementWrapper(useWrapping = true)
private List<Entry> entries;
private String date;
public List<Entry> getEntries() {
return entries;
}
public void setEntries(List<Entry> entries) {
if (this.entries == null){
this.entries = new ArrayList<>(entries.size());
}
this.entries.addAll(entries);
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
class Entry {
private String id;
private String status;
private Person person;
}
class Person {
@JacksonXmlProperty(localName = "Name")
private String name;
@JacksonXmlProperty(localName = "Age")
private String age;
}
然后单元测试:
@Test
void test_xml_XmlMapper() throws Exception {
JacksonXmlModule xmlModule = new JacksonXmlModule();
xmlModule.setDefaultUseWrapper(false);
ObjectMapper xmlMapper = new XmlMapper(xmlModule);
String xmlContent = "your xml file here"
Root bean = xmlMapper.readValue(xmlContent, Root.class);
assertThat(bean.getEntries().size(), Matchers.equalTo(3));
}
我有一个lib枚举,如下所示: 我不能修改这个枚举。我需要从xml反序列化,如下所示: 我知道如何创建和使用混搭与杰克逊。但是如何告诉杰克逊使用外部函数进行反序列化呢?
我有下面的JSON,我正试图使用Jackson API反序列化它 我基本上需要一个附件类,它有一个AttachmentFile对象列表,如下所示: 如何使用自定义反序列化器实现这一点? 谢谢
I'va是一个OID接口,可以由许多具体类型实现: 现在我有一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的: 注意,被序列化,包括类型信息(多态序列化),而被序列化为文本 为此,我将OID接口注释为: 并为每个具体类型分配了类型id: 最后,对容器
我想反序列化表单中的类: 其中文本是加密的,反序列化应该在重建TestFieldEncryptedMessage实例之前取消对值的加密。 我采用的方法非常类似于:https://github.com/codesqueak/jackson-json-crypto 也就是说,我正在构建一个扩展SimpleModule的模块: 如您所见,设置了两个修饰符:EncryptedSerializerModif
我正在尝试为泛型列表创建一个自定义反序列化器。假设我得到了类B的json表示: 其中A是我仅在运行时看到的其他类。我想创建一个反序列化程序,该程序能够将listObject的类型推断为具有内部类型a的list,并将其反序列化,而不是使用默认的hashmap反序列化程序。 我尝试使用上下文反序列化器,类似于这里建议的,然后将其添加为List的自定义反序列化器 但是我不确定我应该如何读取json并在反
我想通过扩展默认的反序列化器来创建自己的反序列化器,在其后面设置更多的值: 如您所见,我还想将此DTO母类重用于其他DTO。 我没有找到任何这样的例子。我真的是世界上第一个 反序列化的“AsUsual”(p,ctxt)应该是什么 我应该使用什么motherclass?JsonDeserializer/StdDeserializer/UntypedObjectDeserializer 反序列化程序会