JAXB/Moxy @XmlPath(".") 在解组期间与 XMLAdapter 冲突 [英] JAXB/Moxy @XmlPath(".") conflicts with the XMLAdapter during the unmarshalling
问题描述
即使在尝试了很多事情之后也无法找到解决方案,因此在此处发布希望获得一些解决方法或解决此问题.
Was unable to find the solution even after trying many things so posting here hoping to get some workaround or fix for this issue.
基本上,如果 @XmlPath(".")
已在 Map
上使用,并且其上有 XMLAdapter
然后它在 unmarshalling
期间失败.marshaling
工作完美,只有 unmarshaling
失败.
Basically, if the @XmlPath(".")
has been used on a Map
and if there is XMLAdapter
on it then it fails during the unmarshalling
. The marshaling
works perfectly only the unmarshalling
fails.
简而言之,我想执行 unmarshalling
这里提到过,但除了 Map
我还会有一个 @XmlElement
.所以一个字段用 (Map field) @XmlPath(".")
和另一个 String 字段用 @XmlElement
注释,然后我想执行 解组
.
In short, I would like to perform the unmarshalling
as mentioned here but along with Map
I will have one more @XmlElement
. So one field is annotated with (Map field) @XmlPath(".")
and another String field with @XmlElement
and then I would like to perform unmarshalling
.
以下是我尝试unmarshal
的XML
:
<Customer xmlns:google="https://google.com">
<name>Batman</name>
<age>2008</age>
<google:sub1>MyValue-1</google:sub1>
<google:sub2>MyValue-1</google:sub2>
</Customer>
下面是 Customer.class
,它将被 unmarshalled
:
@XmlRootElement(name = "Customer")
@XmlType(name = "Customer", propOrder = {"name", "age", "userExtensions"})
@XmlAccessorType(XmlAccessType.FIELD)
@NoArgsConstructor
@Getter
@Setter
@AllArgsConstructor
public class Customer extends Person {
private String name;
private String age;
@XmlPath(".")
@XmlJavaTypeAdapter(TestAdapter.class)
@XmlAnyElement
private Map<String, Object> userExtensions = new HashMap<>();
}
以下是 Main
类,它将 unmarshal
:
Following is the Main
class which will unmarshal
:
public class Unmarshalling {
public static void main(String[] args)
throws JAXBException, XMLStreamException, FactoryConfigurationError, IOException, URISyntaxException, ProcessingException {
final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("customer.xml");
final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
final JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final Customer customer = unmarshaller.unmarshal(xmlStreamReader, Customer.class).getValue();
System.out.println("Read XML : " + customer);
}
}
当我运行这段代码时,我会得到如下输出:
When I run this code I will get the output as:
Read XML : Person(name=Rise Against, age=2000)
它不读取 custom
元素,例如 google:sub1
和 google:sub2
.
Its not reading the custom
elements such as google:sub1
and google:sub2
.
- 还有一个与此类似的问题,但其中提到的解决方法对我不起作用.
- 我在
MAP
上尝试了@XmlAnyElement(lax=true)
,即使这对我不起作用.
- There is one more issue similar to this but the workaround mentioned there did not work for me.
- I tried the
@XmlAnyElement(lax=true)
onMAP
even that did not work for me.
以下是我用于 marshalling
和 unmarhsalling
的 TestAdapter
Map
Following is the TestAdapter
that I am using for marshalling
and unmarhsalling
the Map<String,Object>
public class TestAdapter extends XmlAdapter<Wrapper, Map<String, Object>> {
@Override
public Map<String, Object> unmarshal(Wrapper value) throws Exception {
System.out.println("ADAPTER UNMARSHALLING");
System.out.println(value.getElements());
if (value == null) {
return null;
}
//Loop across all elements within ILMD tag
final Map<String, Object> extensions = new HashMap<>();
for (Object obj : value.getElements()) {
Element element = (Element) obj;
//System.out.println("Node Name : " + element.getNodeName() + " Value : " + element.getTextContent());
final NodeList children = element.getChildNodes();
if (children.getLength() == 1) {
extensions.put(element.getNodeName(), element.getTextContent());
} else {
List<Object> child = new ArrayList<>();
for (int i = 0; i < children.getLength(); i++) {
final Node n = children.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) {
Wrapper wrapper = new Wrapper();
List childElements = new ArrayList();
childElements.add(n);
wrapper.elements = childElements;
child.add(unmarshal(wrapper));
}
}
extensions.put(element.getNodeName(), child);
}
}
return extensions;
}
@SuppressWarnings("unchecked")
@Override
public Wrapper marshal(Map<String, Object> v) throws Exception {
if (v == null) {
return null;
}
Wrapper wrapper = new Wrapper();
List elements = new ArrayList();
for (Map.Entry<String, Object> property : v.entrySet()) {
if (property.getValue() instanceof Map) {
elements.add(new JAXBElement<Wrapper>(new QName(property.getKey()), Wrapper.class, marshal((Map) property.getValue())));
} else {
elements.add(new JAXBElement<String>(new QName(property.getKey()), String.class, property.getValue().toString()));
}
}
wrapper.elements = elements;
return wrapper;
}
}
class Wrapper {
@XmlAnyElement
List elements;
public List getElements() {
return elements;
}
我尝试了很多东西,但直到现在都没有奏效.有人可以看看这个问题并提供您的解决方案.很高兴提供有关此问题的更多信息,因为我花了将近 10 天的时间寻找答案.
I tried many things but nothing worked till now. Can someone please have a look at this issue and provide your solution. Happy to provide any more info with regards to this issue as I have spent nearly 10 days looking for answers.
我尝试了以下方法:
- 又创建了一个变量,并尝试仅在解组期间使用它,但这也失败了.
- 尝试再创建一个字段,然后在其上使用
@XmlAnyElement
,但这也没有按我的预期工作.
- Created one more variable and tried to use it only during unmarshalling but that's also failing.
- Tried to create one more field then used the
@XmlAnyElement
on it but that's also not working as I expected.
尝试了更多的东西,但没有任何帮助.
Tried few more things but nothing helped.
一切都失败了.我试图从 MOXY
调试代码,但我无法在其中了解很多事情.对这个问题的任何帮助都会对我很有帮助.
Everything is failing. I tried to debug the code from MOXY
but I am unable to follow many things there. Any help with this issue would be really helpful for me.
推荐答案
我能够通过使用 BeforeMarshal
和 AfterMarshal
方法得到它.在这里发帖,以便将来对某人有所帮助:
I was able to get it by using the BeforeMarshal
and AfterMarshal
methods. Posting here so it can be helpful to someone in the future:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA")
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name = "extension")
@XmlType(name = "extension", propOrder = {"name", "age", "otherElements"})
@XmlAccessorType(XmlAccessType.FIELD)
@Getter
@Setter
@AllArgsConstructor
@ToString
@NoArgsConstructor
public class Customer {
@XmlTransient
private String isA;
@XmlPath("customer/name/text()")
private String name;
@XmlPath("customer/age/text()")
private String age;
@XmlAnyElement(lax = true)
@JsonIgnore
@XmlPath("customer")
private List<Object> otherElements = new ArrayList<>();
@JsonIgnore
@XmlTransient
private Map<String, Object> userExtensions = new HashMap<>();
@JsonAnyGetter
@JsonSerialize(using = CustomExtensionsSerializer.class)
public Map<String, Object> getUserExtensions() {
return userExtensions;
}
@JsonAnySetter
public void setUserExtensions(String key, Object value) {
userExtensions.put(key, value);
}
private void beforeMarshal(Marshaller m) throws ParserConfigurationException {
System.out.println("Before Marshalling User Extension: " + userExtensions);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
otherElements = extensionsModifier.Marshalling(userExtensions);
System.out.println("Before Marshalling Final Other Elements " + otherElements);
userExtensions = new HashMap<>();
}
private void afterUnmarshal(Unmarshaller m, Object parent) throws ParserConfigurationException {
System.out.println("After Unmarshalling : " + otherElements);
ExtensionsModifier extensionsModifier = new ExtensionsModifier();
userExtensions = extensionsModifier.Unmarshalling(otherElements);
System.out.println("Final User Extensions : " + userExtensions);
otherElements = new ArrayList();
}
}
完整的答案可以在这里找到:https://stackoverflow.com/a/67923216/7584240
The complete answer can be found here: https://stackoverflow.com/a/67923216/7584240
这篇关于JAXB/Moxy @XmlPath(".") 在解组期间与 XMLAdapter 冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!