问题描述
即使尝试了很多方法也无法找到解决方案,因此在此处发帖希望能找到一些解决方法或解决此问题。
基本上,如果在 @XmlPath(".")
上使用了 Map
并且上面有 XMLAdapter
,那么它会在 unmarshalling
期间失败。 marshaling
完美运行,只有 unmarshalling
失败。
简而言之,我想演奏unmarshalling
as mentioned here,但除了Map
,我还要演奏@XmlElement
。所以一个字段用 (Map field) @XmlPath(".")
注释,另一个字符串字段用 @XmlElement
注释,然后我想执行 unmarshalling
。
以下是我试图XML
的{{1}}:
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>
的 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
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);
}
}
它不读取 Read XML : Person(name=Rise Against,age=2000)
元素,例如 custom
和 google:sub1
。
- 还有一个 issue similar to this,但那里提到的解决方法对我不起作用。
- 我在
google:sub2
上尝试了@XmlAnyElement(lax=true)
,即使这对我不起作用。
以下是我用于 MAP
的 TestAdapter
和 marshalling
unmarhsalling
Map<String,Object>
我尝试了很多东西,但到目前为止没有任何效果。有人可以看看这个问题并提供您的解决方案。很高兴提供有关此问题的更多信息,因为我花了将近 10 天的时间寻找答案。
我尝试了以下操作:
- 又创建了一个变量并尝试仅在解组期间使用它,但也失败了。
- 尝试再创建一个字段,然后在其上使用
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; }
,但这也没有按我预期的那样工作。
尝试了更多的东西,但没有任何帮助。
一切都失败了。我试图从 @XmlAnyElement
调试代码,但我无法在那里跟踪很多事情。对此问题的任何帮助都会对我很有帮助。
解决方法
我能够通过使用 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
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