【发布时间】:2021-08-10 08:16:25
【问题描述】:
我正在尝试解组 XML 并将其映射到 Java POJO。我的 XML 可以包含一些用户定义的元素,这些元素可以是随机的,所以我想存储它们。经过研究,我发现我可以使用@XmlAnyElement(lax=true)。我正在尝试将XMLAdapter 与@XmlAnyElement 一起使用,但由于某种原因,我的XMLAdapter 中的unmarshal 方法根本没有被调用,因为我无法映射user-defined 字段。
有人可以向我解释如何将unmarshaluser-defined 字段添加到我的Map<String,Object> 以获取marshalling,一切正常,我正在使用mentioned here 方法。但是unmarshalling 根本没有被调用,这让我有点困惑。
下面是我的XML,必须是unmarshalled。 (请注意,namespace 可以是动态的和用户定义的,可能会在每个 xml 中更改):
<Customer xmlns:google="https://google.com">
<name>Batman</name>
<google:main>
<google:sub>bye</google:sub>
</google:main>
</Customer>
下面是我的Customer 类,XML 需要是unmarshalled;
@XmlRootElement(name = "Customer")
@XmlType(name = "Customer", propOrder = {"name", "others"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
private String name;
@XmlAnyElement(lax = true)
@XmlJavaTypeAdapter(TestAdapter.class)
private Map<String, Object> others = new HashMap<>();
//Getter Setter and other constructors
}
以下是我的XMLAdapter (TestAdapter) 类,它将用于marshalling 和unmarshalling user-defined 字段。 unmarshalling 方法根本没有被调用。但是 marshalling 方法基于 the code provided here 可以正常工作。
class TestAdapter extends XmlAdapter<Wrapper, Map<String,Object>> {
@Override
public Map<String,Object> unmarshal(Wrapper value) throws Exception {
//Method not being called at all the following SYSTEM.OUT is NOT PRINTED
System.out.println("INSIDE UNMARSHALLING METHOD TEST");
System.out.println(value.getElements());
return null;
}
@Override
public Wrapper marshal(Map<String,Object> v) throws Exception {
return null;
}
}
class Wrapper {
@XmlAnyElement
List elements;
}
我使用了package-info.java 文件,里面填充了以下内容:
@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://google.com", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED)
package io.model.jaxb;
我进行了很多研究,但找不到任何类似的答案。此外,尝试了很多东西,但都没有奏效。因此,在这里发布相同的内容并寻找一些建议或解决方法。
关于unmarshalling,我几乎没有疑问:
- 为什么我的
XMLAdapter TestAdapter.classunmarshal方法在解组期间没有被调用? - 我如何
unmarshal可以随命名空间随机出现的 XML 字段? - 是我做错了什么还是我应该做些什么来读取动态显示的命名空间和元素?
*** FOLLOWING IS EDITED SECTION BASED ON RESPONSE FROM Thomas Fritsch ****
根据回复,我已经编辑了我的课程,但仍无法按预期工作:
@XmlRootElement(name = "Customer")
@XmlType(name = "Customer", propOrder = {"name", "others"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
private String name;
@JsonIgnore
@XmlJavaTypeAdapter(TestAdapter.class)
private List<Object> others;
@XmlTransient
@XmlAnyElement(lax = true)
private List<Element> another = new ArrayList<>();
}
所以发生的情况是,如果我使用@XmlTransient,那么another 字段将不会在unmarshalling 期间填充,我需要保留它@XmlTransient,因为我不希望在marshalling 期间同样使用它我为Map<String, Object> others 制作了@JsonIgnore,因为在unmarshalling 期间我不需要它,但两者相互冲突,无法获得所需的输出。
我的主要目标是将XML 文件转换为JSON,反之亦然。对于上面提到的XML 文件,我想在JSON 中获得以下输出:
{
"Customer": {
"name": "BATMAN",
"google:main": {
"google:sub": "bye"
}
}
}
同样,当我转换这个JSON 时,我应该得到原始的XML。
以下是我的Main.class:
class Main {
public static void main(String[] args) throws JAXBException, XMLStreamException, JsonProcessingException {
//XML to JSON
JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("Customer.xml");
final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
final XMLStreamReader streamReader = xmlInputFactory.createXMLStreamReader(inputStream);
final Customer customer = unmarshaller.unmarshal(streamReader, Customer.class).getValue();
final ObjectMapper objectMapper = new ObjectMapper();
final String jsonEvent = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
System.out.println(jsonEvent);
//JSON to XML
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(customer, System.out);
}
}
【问题讨论】:
标签: java xml jaxb unmarshalling moxy