Open nezda opened 11 years ago
Correct -- currently there is no way to handle synonyms (either between attribute or element; or between properties with different namespace). This is unfortunate, but will also be difficult to correct.
I have a similar issue where the source XML has the same attribute name for different namespaces, e.g.
xml
<x:someNode
xmlns:x="http://x.com/xsd"
xmlns:y="http://y.com/xsd"
x:version="1"
y:version="9" />
As far as I can tell it seems that there both the BeanDeserializer and FromXmlParser have to change to take into account the namespaces. Is that correct?
Yes; while namespace information is exposed by underlying parser, and although property name can pass information, the way deserializer/property lookup works is to only use local name. And since only XML has additional concept, making things work together is difficult.
@cowtowncoder The other cases I can think of Smile, JSON, and YAML don't support a concept like XML namespaces. It sounds to me like this use case isn't really something Jackson should support and that one should use more specialized XML tools. What is your opinion about that? Do you want to see Jackson change to support namespaces?
@arielvalentin I am bit torn here, having written a few XML libraries (Woodstox, Aalto). Ideally, Jackson would be able to support exact matching of XML namespaces.
At the same time, due to practical limitations, at this point if use of namespaces is integral (and not just casual, where there are no collisions), it is reasonable to use JAXB for data-binding.
So: if feasible, I would really like to see Jackson handle namespace binding, resolution properly. It just has to be done in a way that works well without requiring other backends to support concept they have no use for. In theory Avro backend also has namespaces, for example; in practice, their use is quite limited as names are never included in encoded data. They are only used at schema level.
I'm stuck on this issue too, unfortunately I cannot change the source XML that i'm deserializing as it's not mine. Any workarounds?
@kamransaleem I found this thread to be a valid workaround. The answer in this threat uses JsonIgnore and JsonAnySetter :
Before:
public static class CustomResult {
public CustomResult() {}
@XmlElement(name = "service")
private String service;
@XmlElement(name = "date")
private String date;
@XmlElement(name = "status")
private Integer status;
@XmlElement(name = "service")
private Service statusObj;
}
Workaround:
@XmlRootElement(name = "result")
public static class CustomResult {
public CustomResult() {}
@JsonIgnore
private List<Object> service = new ArrayList<>();
@XmlElement(name = "date")
private String date;
@XmlElement(name = "status")
private Integer status;
@JsonAnySetter
public void setServices(String name, Object value) {
if (value instanceof String) {
service.add(value);
}
if (value instanceof Map) {
// TODO create new Service object from map entries.
}
// error?
}
}
see here
Additional hint - if the value is a map, I use another object mapper to convert it to the respective object. If you need more code examples feel free to ask.
@sunoce Thanks for the sample it works great!
If an element has an attribute and sub-element with the same name, the attribute seems to be ignored and the element value used, despite collision resolving configuration with
@JacksonXmlProperty(localName="state", isAttribute=true)
(for colliding namestate
). Here is concrete exampleThe following input should deserialize the appropriate distinct values into the appropriate distinct fields:
<Wrapper state='stateAttr'><state>stateElement</state></Wrapper>
Here is a failing test snippet for
com.fasterxml.jackson.dataformat.xml.failing.TestDeserialization