JAXB/Moxy @XmlPath(".") 在解组期间与 XMLAdapter 冲突

JAXB/Moxy @XmlPath(".") conflicts with the XMLAdapter during the unmarshalling

即使尝试了很多方法也无法找到解决方案,因此在此处发帖希望能找到一些解决方法或解决此问题。

基本上,如果 @XmlPath(".") 已在 Map 上使用,并且如果上面有 XMLAdapter,则它在 unmarshalling 期间失败。 marshaling 完美运行,只有 unmarshalling 失败。

简而言之,我想执行 unmarshalling as mentioned here 但是除了 Map 我还会再执行一个 @XmlElement。所以一个字段用 (Map field) @XmlPath(".") 注释,另一个字符串字段用 @XmlElement 注释,然后我想执行 unmarshalling.

以下是我正在尝试 XML 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 class 它将 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:sub1google:sub2

  1. 还有一个 但那里提到的解决方法对我不起作用。
  2. 我在 MAP 上尝试了 @XmlAnyElement(lax=true),但它对我不起作用。

以下是我用于 marshallingunmarhsallingTestAdapter 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 天的时间寻找答案。

我尝试了以下操作:

  1. 再创建一个变量并尝试仅在解组期间使用它,但同样失败。
  2. 尝试再创建一个字段,然后在其上使用 @XmlAnyElement,但也没有像我预期的那样工作。

尝试了更多的东西,但没有任何帮助。

一切都在失败。我试图从 MOXY 调试代码,但我无法了解那里的许多事情。对这个问题的任何帮助对我来说真的很有帮助。

我可以使用 BeforeMarshalAfterMarshal 方法得到它。在这里发帖,以便将来对某人有所帮助:

@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();
    }
}

完整的答案可以在这里找到: