有了这个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
}
....
}
不安全的解决方案
答案 0 :(得分:0)
我已经能够重现你所看到的问题,但还没有找到原因。您可以使用以下错误来跟踪此问题的进度:
答案 1 :(得分:0)
尝试了很多事情后,我找到了解决此问题的方法。我想在这里发布相同的内容,以便将来对其他人有所帮助。领导在大约 5 年前就确认了这个问题,但他们似乎还没有解决这个问题,我也面临着类似的问题。
基本上,我们可以使用 beforeMarshal
和 afterUnmarshal
方法来更改字段中的值。
List<Object>
和 @XmlAnyElement(lax=true)
创建一个字段 Map<String,Object>
。@XmlPath(".")
和 XMLAdapter
类。Map<String, Object>
标记字段 @XmlTransient
。现在在 beforeMarshal
和 afterMarshal
字段中,您可以交换数据。在 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