@XmlPath(“。”)与@XmlAdapter冲突

时间:2015-01-04 11:36:12

标签: jaxb moxy

有了这个Jaxb Xml定义,我尝试通过添加@XmlPath(".")来删除Map Elements Wrapper,但它在unmarchaling期间导致异常

@XmlRootElement
public abstract class ViewElement{
    @XmlJavaTypeAdapter(value=EventAdapter.class)   
    public Map<Event, String> getEvents() {     
    }
    private transient Class entityType;
    public Class getEntityType() {
        return entityType;
    }
}

EventAdapter是

public class EventAdapter extends XmlAdapter<EventAdapter.AdaptedMap, Map<Event, String>> { 
    public static class AdaptedMap {
        @XmlVariableNode("key")
        List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
    }
    public static class AdaptedEntry {
        @XmlTransient
        public String key;
        @XmlValue
        public String value;
    }
    .....       
}

我的输出是

<element>
   <events>
      <onCellEdit>do some thing<onCellEdit>
   </events>
   <entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>

我尝试添加<events>

删除@XmlPath(".")代码
@XmlPath(".")
@XmlJavaTypeAdapter(value=EventAdapter.class)   
public Map<Event, String> getEvents() {     
}

输出很好

<element>
   <onCellEdit>do some thing<onCellEdit>       
   <entityType>com.agitech.erp.model.erp.ErpFolder</entityType>
<element>

但是未结合失败

Caused by: Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.6.0.v20140809-296a69f): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[entityType-->view.entityType/text()]] with descriptor [XMLDescriptor(com.agitech.erp.view.BeanView --> [DatabaseTable(view), DatabaseTable(viewFrame), DatabaseTable(viewElement)])], could not be converted to [class java.lang.Class].
Internal Exception: java.lang.ClassNotFoundException: 
    at org.eclipse.persistence.exceptions.ConversionException.couldNotBeConvertedToClass(ConversionException.java:95)
    at org.eclipse.persistence.internal.helper.ConversionManager.convertObjectToClass(ConversionManager.java:446)

Debuging Jaxb带我到了行

org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue

public void endElement(XPathFragment xPathFragment, UnmarshalRecord unmarshalRecord) {
    ...
    line 205 unmarshalRecord.setAttributeValue(convertedValue, xmlDirectMapping);
}

在取消实体类型值的过程中,UnmarshalRecordImpl.currentObj包含EventAdapter而不是父元素

我修改org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl

public XPathNode getNonAttributeXPathNode(String namespaceURI, String localName, String qName, Attributes attributes) {
....
    if(null == resultNode && null == nonPredicateNode) {
        // ANY MAPPING
        resultNode = xPathNode.getAnyNode();
// by default it return the EventAdapter, changing it to NULL fix my problem
    }
....
}

不安全的解决方案

2 个答案:

答案 0 :(得分:0)

我已经能够重现你所看到的问题,但还没有找到原因。您可以使用以下错误来跟踪此问题的进度:

答案 1 :(得分:0)

尝试了很多事情后,我找到了解决此问题的方法。我想在这里发布相同的内容,以便将来对其他人有所帮助。领导在大约 5 年前就确认了这个问题,但他们似乎还没有解决这个问题,我也面临着类似的问题。

基本上,我们可以使用 beforeMarshalafterUnmarshal 方法来更改字段中的值。

  1. 您需要使用 List<Object>@XmlAnyElement(lax=true) 创建一个字段 Map<String,Object>
  2. 删除 @XmlPath(".")XMLAdapter 类。
  3. Map<String, Object> 标记字段 @XmlTransient

现在在 beforeMarshalafterMarshal 字段中,您可以交换数据。在 unmarshal 中的 beforeunmarshal, 期间,所有未知字段值都将出现在 List<Object> 循环中并将其添加到 Map<String, Object>

同样在 marshaling 期间,您可以通过创建 Map<String, Object> 元素将值 List<Object> 移动到 DOM

Marshaling 所有值都添加到 root,因为 DOM Elements 存在并且在 Unmarshaling 期间首先读取已知值,然后将未知值存储在 {{1} 中} 由于List<Object>

我使用 @XmlAnyElement 类创建了一个示例,您可以根据需要对其进行相应修改。

Customer

您可以在此处参考 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "isA") @JsonInclude(Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) @XmlRootElement(name = "Customer") @XmlType(name = "Customer", propOrder = {"name", "age", "otherElements"}) @XmlAccessorType(XmlAccessType.FIELD) @Getter @Setter @AllArgsConstructor @ToString @NoArgsConstructor public class Customer { @XmlTransient private String isA; private String name; private String age; @XmlAnyElement(lax = true) @JsonIgnore 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); otherElements = new ArrayList(); } } 的创建:https://stackoverflow.com/a/24239105/7584240

您可以在此处参考我的完整答案:https://stackoverflow.com/a/67923216/7584240