I am trying to unmarshal an XML into an object that I expect should have a certain field. However, I do not want to marshal that object into an XML that contains it. What I like would be similar to this:
@XmlRootElement(name = "User")
public class User {
private String name;
@XmlTransient
public String getName() {
return this.name
}
@XmlElement(name = "Name")
public void setName(String name) {
this.name = name
}
}
However, this would not work due to the conflicting annotations, as I can't use any other XML annotations with @XmlTransient
. I have also tried to add the @XmlTransient
annotation on the field itself instead of the getter and have set this option:
XmlAccessorType(XmlAccessType.FIELD)
In addition, I kept the @XmlElement
annotation on the setter, and that did absolutely nothing in terms of excluding the field from being marshalled.
I would like to keep the @XmlElement
annotation, since I like being able to translate a field with a different name (here it is just a capitalization difference) into whichever field I want.
I also cannot delete the getter, as I do use it in the application.
Given that, I don't know what my options are at this point, other than writing an adapter (which I could do, but if there is another solution, I'd rather not use a custom adapter because of this one field). Any help would be greatly appreciated.
I think your problem lies in the idea itself: @XmlTransient
tells the marshaller to completely ignore that field/property when doing its job, so I'd guess it's not what you're looking for, as you wouldn't want to (and couldn't anyway) set a custom name for the marshalled element if you wanted to omit it in the first place.
Another point is that with JAXB, public getters/setters are paired with their respective counterparts, so the annotations applied to both are "merged" when read (hence why you can't use @XmlTransient
in the getter and @XmlElement
in the setter at the same time), and thus their positions are also interchangeable.
Also, just for clarity, @XmlAccessorType
only interferes in the default handling of public
members. If the field or method in question is not public
, it won't affect how it will be handled by default.
Now for the solutions:
If you want to omit it all:
With private
field and public
getter/setter, just use @XmlTransient
once in the getter or setter and nothing else.
@XmlRootElement(name = "User")
public class User {
private String name;
@XmlTransient
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
If both are public
, use @XmlTransient
once in the field and once again in either getter or setter.
@XmlRootElement(name = "User")
public class User {
@XmlTransient
public String name;
@XmlTransient
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
If instead you want to keep it with a custom name:
If the field is private
, use only @XmlElement
once in the getter or setter.
@XmlRootElement(name = "User")
public class User {
private String name;
@XmlElement(name = "Name")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
If both field and accessors are public (and there's no @XmlAccessorType
or it's set to XmlAccessType.PUBLIC_MEMBER
), then you'll have to use @XmlTransient
in either field or getter/setter and @XmlElement
in the other (they'll be interchangeable if all the methods do is just reading/writing the value, as in this case).
@XmlRootElement(name = "User")
public class User {
@XmlTransient
public String name;
@XmlElement(name = "Name")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}