Java jackson xml列出识别为重复密钥的反序列化
我正在尝试使用Java jackson xml列出识别为重复密钥的反序列化,java,json,xml,list,jackson,Java,Json,Xml,List,Jackson,我正在尝试使用jackson-2.5.1和jackson-dataformat-xml-2.5.1 xml结构是从web服务器接收的,未知,因此我无法使用java类来表示对象,我正试图使用ObjectMapper.readTree直接转换为TreeNode 我的问题是jackson无法解析列表。它只接受列表的最后一项。 代码: 如果我在重复键上启用失败xmlMapper.enable(反序列化功能。读取树键时失败),则引发异常: com.fasterxml.jackson.databind.Js
jackson-2.5.1
和jackson-dataformat-xml-2.5.1
xml结构是从web服务器接收的,未知,因此我无法使用java类来表示对象,我正试图使用
ObjectMapper.readTree
直接转换为TreeNode
我的问题是jackson无法解析列表。它只接受列表的最后一项。代码: 如果我在重复键上启用失败
xmlMapper.enable(反序列化功能。读取树键时失败)
,则引发异常:com.fasterxml.jackson.databind.JsonMappingException:ObjectNode的重复字段“item”:在读取失败时不允许重复树键启用
是否有任何功能可以修复此问题?有没有一种方法可以让我编写自定义反序列化程序,以便在出现重复键时将它们转换为数组?您可以捕获该异常并执行以下操作:
List<MyClass> myObjects = mapper.readValue(input, new TypeReference<List<MyClass>>(){});
List myObjects=mapper.readValue(输入,new-TypeReference(){});
(从这里得到的)
这是一个黑客的方法,你必须弄清楚如何从那里恢复 我遇到了同样的问题,并决定使用直截了当的DOM来实现自己的功能。主要问题是XML并不像JSon那样真正适合映射列表对象类型映射。但是,根据一些假设,仍然有可能:
public class DeXML {
public DeXML() {}
public Map<String, Object> toMap(InputStream is) {
return toMap(new InputSource(is));
}
public Map<String, Object> toMap(String xml) {
return toMap(new InputSource(new StringReader(xml)));
}
private Map<String, Object> toMap(InputSource input) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(input);
document.getDocumentElement().normalize();
Element root = document.getDocumentElement();
return visitChildNode(root);
} catch (ParserConfigurationException | SAXException | IOException e) {
throw new RuntimeException(e);
}
}
// Check if node type is TEXT or CDATA and contains actual text (i.e. ignore
// white space).
private boolean isText(Node node) {
return ((node.getNodeType() == Element.TEXT_NODE || node.getNodeType() == Element.CDATA_SECTION_NODE)
&& node.getNodeValue() != null && !node.getNodeValue().trim().isEmpty());
}
private Map<String, Object> visitChildNode(Node node) {
Map<String, Object> map = new HashMap<>();
// Add the plain attributes to the map - fortunately, no duplicate attributes are allowed.
if (node.hasAttributes()) {
NamedNodeMap nodeMap = node.getAttributes();
for (int j = 0; j < nodeMap.getLength(); j++) {
Node attribute = nodeMap.item(j);
map.put(attribute.getNodeName(), attribute.getNodeValue());
}
}
NodeList nodeList = node.getChildNodes();
// Any text children to add to the map?
List<Object> list = new ArrayList<>();
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
Node child = node.getChildNodes().item(i);
if (isText(child)) {
list.add(child.getNodeValue());
}
}
if (!list.isEmpty()) {
if (list.size() > 1) {
map.put(null, list);
} else {
map.put(null, list.get(0));
}
}
// Process the element children.
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
// Ignore anything but element nodes.
Node child = nodeList.item(i);
if (child.getNodeType() != Element.ELEMENT_NODE) {
continue;
}
// Get the subtree.
Map<String, Object> childsMap = visitChildNode(child);
// Now, check if this is key already exists in the map. If it does
// and is not a List yet (if it is already a List, simply add the
// new structure to it), create a new List, add it to the map and
// put both elements in it.
if (map.containsKey(child.getNodeName())) {
Object value = map.get(child.getNodeName());
List<Object> multiple = null;
if (value instanceof List) {
multiple = (List<Object>)value;
} else {
map.put(child.getNodeName(), multiple = new ArrayList<>());
multiple.add(value);
}
multiple.add(childsMap);
} else {
map.put(child.getNodeName(), childsMap);
}
}
return map;
}
}
公共类DeXML{
公共DeXML(){}
公共映射toMap(输入流为){
返回toMap(新输入源(is));
}
公共映射toMap(字符串xml){
返回toMap(新的InputSource(新的StringReader(xml));
}
私有映射toMap(输入源输入){
试一试{
DocumentBuilderFactory工厂=DocumentBuilderFactory.newInstance();
DocumentBuilder=factory.newDocumentBuilder();
Document=builder.parse(输入);
document.getDocumentElement().normalize();
元素根=document.getDocumentElement();
返回visitChildNode(root);
}捕获(ParserConfiguration异常| SAXException | IOE异常){
抛出新的运行时异常(e);
}
}
//检查节点类型是否为文本或CDATA并且包含实际文本(即忽略
//空白)。
专用布尔isText(节点){
返回((node.getNodeType()==Element.TEXT_节点| | node.getNodeType()==Element.CDATA_节_节点)
&&node.getNodeValue()!=null&!node.getNodeValue().trim().isEmpty());
}
私有映射访问ChildNode(节点){
Map Map=newhashmap();
//将普通属性添加到地图-幸运的是,不允许重复属性。
if(node.hasAttributes()){
NamedNodeMap nodeMap=node.getAttributes();
对于(int j=0;j1){
map.put(null,list);
}否则{
map.put(null,list.get(0));
}
}
//处理元素的子元素。
对于(int i=0;i
库支持此XML
String xml = "<root><name>john</name><list><item>val1</item>val2<item>val3</item></list></root>";
String json = U.xmlToJson(xml);
System.out.println(json);
我使用这种方法:
大小==1
的列表 @Test
public void xmlToJson() {
String xml = "<root><name>john</name><list><item>val1</item>val2<item>val3</item></list></root>";
Map<String, Object> jsonResult = readXmlToMap(xml);
String jsonString = toString(jsonResult);
System.out.println(jsonString);
}
private Map<String, Object> readXmlToMap(String xml) {
try {
ObjectMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new SimpleModule().addDeserializer(Object.class, new UntypedObjectDeserializer() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected Map<String, Object> mapObject(JsonParser jp, DeserializationContext ctxt) throws IOException {
JsonToken t = jp.getCurrentToken();
Multimap<String, Object> result = ArrayListMultimap.create();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
if (t == JsonToken.END_OBJECT) {
return (Map) result.asMap();
}
do {
String fieldName = jp.getCurrentName();
jp.nextToken();
result.put(fieldName, deserialize(jp, ctxt));
} while (jp.nextToken() != JsonToken.END_OBJECT);
return (Map) result.asMap();
}
}));
return (Map) xmlMapper.readValue(xml, Object.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static public String toString(Object obj) {
try {
ObjectMapper jsonMapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true);
StringWriter w = new StringWriter();
jsonMapper.writeValue(w, obj);
return w.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
总之,这是该方法的一个变种,没有guava multimap:
这里使用相同的方法:
这不是我的用例。首先,我没有java类。第二件事,这个列表嵌入在xml的某个地方,它不是根目录下的对象列表。你可能运气不好
String xml = "<root><name>john</name><list><item>val1</item>val2<item>val3</item></list></root>";
String json = U.xmlToJson(xml);
System.out.println(json);
{
"root": {
"name": "john",
"list": {
"item": [
"val1",
{
"#item": {
"#text": "val2"
}
},
"val3"
]
}
},
"#omit-xml-declaration": "yes"
}
@Test
public void xmlToJson() {
String xml = "<root><name>john</name><list><item>val1</item>val2<item>val3</item></list></root>";
Map<String, Object> jsonResult = readXmlToMap(xml);
String jsonString = toString(jsonResult);
System.out.println(jsonString);
}
private Map<String, Object> readXmlToMap(String xml) {
try {
ObjectMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new SimpleModule().addDeserializer(Object.class, new UntypedObjectDeserializer() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected Map<String, Object> mapObject(JsonParser jp, DeserializationContext ctxt) throws IOException {
JsonToken t = jp.getCurrentToken();
Multimap<String, Object> result = ArrayListMultimap.create();
if (t == JsonToken.START_OBJECT) {
t = jp.nextToken();
}
if (t == JsonToken.END_OBJECT) {
return (Map) result.asMap();
}
do {
String fieldName = jp.getCurrentName();
jp.nextToken();
result.put(fieldName, deserialize(jp, ctxt));
} while (jp.nextToken() != JsonToken.END_OBJECT);
return (Map) result.asMap();
}
}));
return (Map) xmlMapper.readValue(xml, Object.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static public String toString(Object obj) {
try {
ObjectMapper jsonMapper = new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true)
.configure(SerializationFeature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED, true);
StringWriter w = new StringWriter();
jsonMapper.writeValue(w, obj);
return w.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
{
"list" : {
"item" : [ "val1", "val3" ]
},
"name" : "john"
}