本文介绍了JAXB/Moxy @XmlPath(".") 在解组过程中与 XMLAdapter 发生冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 即使尝试了很多方法也无法找到解决方案,因此在此处发帖希望能找到一些解决方法或解决此问题.基本上,如果 @XmlPath(".") 已用于 Map 并且上面有 XMLAdapter然后它在 unmarshalling 期间失败.marshaling 完美运行,只有 unmarshalling 失败.简而言之,我想执行解组 正如这里提到的,但与 Map 一起,我还有一个 @XmlElement.所以一个字段用 (Map field) @XmlPath(".") 注释,另一个 String 字段用 @XmlElement 注释,然后我想执行 解组.以下是我试图解组的XML:<name>蝙蝠侠</name><age>2008</age><google:sub1>MyValue-1</google:sub1><google:sub2>MyValue-1</google:sub2></客户>以下是将被解组的Customer.class:@XmlRootElement(name = "Customer")@XmlType(name = "Customer", propOrder = {"name", "age", "userExtensions"})@XmlAccessorType(XmlAccessType.FIELD)@NoArgsConstructor@Getter@Setter@AllArgsConstructor公共类客户扩展人{私人字符串名称;私人字符串年龄;@XmlPath(".")@XmlJavaTypeAdapter(TestAdapter.class)@XmlAnyElement私有映射userExtensions = new HashMap();}以下是将解组的Main类:公共类解组{public static void main(String[] args)抛出 JAXBException、XMLStreamException、FactoryConfigurationError、IOException、URISyntaxException、ProcessingException {final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream(customer.xml");最终 XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);最终 JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);最终解组器 unmarshaller = jaxbContext.createUnmarshaller();最终客户 customer = unmarshaller.unmarshal(xmlStreamReader, Customer.class).getValue();System.out.println("读取 XML :" + 客户);}}当我运行这段代码时,我会得到如下输出:读取 XML : Person(name=Rise against, age=2000)它不会读取 custom 元素,例如 google:sub1 和 google:sub2.还有一个与此类似的问题,但那里提到的解决方法对我不起作用.我在 MAP 上尝试了 @XmlAnyElement(lax=true) 即使这对我不起作用.以下是我用于 marshalling 和 unmarhsalling 的 TestAdapter Mappublic class TestAdapter extends XmlAdapter>{@覆盖公共地图unmarshal(Wrapper value) 抛出异常 {System.out.println(适配器解组");System.out.println(value.getElements());如果(值 == 空){返回空;}//遍历ILMD标签内的所有元素最终映射extensions = new HashMap();for (Object obj : value.getElements()) {元素元素=(元素)obj;//System.out.println("节点名称:" + element.getNodeName() +"值:" + element.getTextContent());final NodeList children = element.getChildNodes();如果 (children.getLength() == 1) {extensions.put(element.getNodeName(), element.getTextContent());} 别的 {列表child = new ArrayList();for (int i = 0; i < children.getLength(); i++) {最终节点 n = children.item(i);if (n.getNodeType() == Node.ELEMENT_NODE) {包装器包装器 = new Wrapper();List childElements = new ArrayList();childElements.add(n);wrapper.elements = childElements;child.add(unmarshal(wrapper));}}extensions.put(element.getNodeName(), child);}}退货延期;}@SuppressWarnings(未选中")@覆盖public Wrapper marshal(Map v) 抛出异常 {如果(v == 空){返回空;}包装器包装器 = new Wrapper();列表元素 = new ArrayList();for (Map.Entry 属性 : v.entrySet()) {if (property.getValue() instanceof Map) {element.add(new JAXBElement(new QName(property.getKey()), Wrapper.class, marshal((Map) property.getValue())));} 别的 {element.add(new JAXBElement(new QName(property.getKey()), String.class, property.getValue().toString()));}}包装器元素 = 元素;返回包装器;}}类包装{@XmlAnyElement列表元素;公共列表 getElements() {返回元素;}我尝试了很多东西,但到目前为止没有任何效果.有人可以看看这个问题并提供您的解决方案.很高兴提供有关此问题的更多信息,因为我花了将近 10 天的时间寻找答案.我尝试了以下操作:又创建了一个变量并尝试仅在解组期间使用它,但也失败了.尝试再创建一个字段,然后在其上使用 @XmlAnyElement 但这也没有按我预期的那样工作.尝试了更多的东西,但没有任何帮助.一切都失败了.我试图从 MOXY 调试代码,但我无法在那里跟踪很多东西.对此问题的任何帮助都会对我很有帮助. 解决方案 我能够通过使用 BeforeMarshal 和 AfterMarshal 方法获得它.在这里发布,以便将来对某人有所帮助:@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公共类客户{@XmlTransient私有字符串 isA;@XmlPath("客户/姓名/文本()")私人字符串名称;@XmlPath("客户/年龄/文本()")私人字符串年龄;@XmlAnyElement(lax = true)@JsonIgnore@XmlPath(客户")私人列表otherElements = new ArrayList();@JsonIgnore@XmlTransient私有映射userExtensions = new HashMap();@JsonAnyGetter@JsonSerialize(使用 = CustomExtensionsSerializer.class)公共地图getUserExtensions() {返回用户扩展;}@JsonAnySetterpublic void setUserExtensions(String key, Object value) {userExtensions.put(key, value);}private void beforeMarshal(Marshaller m) 抛出 ParserConfigurationException {System.out.println("编组用户扩展前:" + userExtensions);ExtensionsModifier extensionsModifier = new ExtensionsModifier();otherElements = extensionsModifier.Marshalling(userExtensions);System.out.println("在编组最终其他元素之前" + otherElements);userExtensions = new HashMap();}private void afterUnmarshal(Unmarshaller m, Object parent) 抛出 ParserConfigurationException {System.out.println("解组后:" + otherElements);ExtensionsModifier extensionsModifier = new ExtensionsModifier();userExtensions = extensionsModifier.Unmarshalling(otherElements);System.out.println("最终用户扩展:" + userExtensions);其他元素 = 新的 ArrayList();}}完整答案可以在这里找到:https://stackoverflow.com/a/67923216/7584240>Was unable to find the solution even after trying many things so posting here hoping to get some workaround or fix for this issue.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.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.Following is the XML that I am trying to unmarshal:<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>Following is the Customer.class to which it will be unmarshalled:@XmlRootElement(name = "Customer")@XmlType(name = "Customer", propOrder = {"name", "age", "userExtensions"})@XmlAccessorType(XmlAccessType.FIELD)@NoArgsConstructor@Getter@Setter@AllArgsConstructorpublic class Customer extends Person { private String name; private String age; @XmlPath(".") @XmlJavaTypeAdapter(TestAdapter.class) @XmlAnyElement private Map<String, Object> userExtensions = new HashMap<>();}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)Its not reading the custom elements such as google:sub1 and google:sub2.There is one more issue similar to this but the workaround mentioned there did not work for me.I tried the @XmlAnyElement(lax=true) on MAP even that did not work for me.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; }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.I tried following things: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.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. 解决方案 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@NoArgsConstructorpublic 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(); }}The complete answer can be found here: https://stackoverflow.com/a/67923216/7584240 这篇关于JAXB/Moxy @XmlPath(".") 在解组过程中与 XMLAdapter 发生冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-01 07:50