Excluding fields in JAXB

I have 2 classes:

@XmlRootElement
public class A {

    private Long id;
    private B b;

    // setters and getters
}

and

@XmlRootElement
public class B {

    private Long id;
    private String field1;
    private String field2;

    // setters and getters
}

By default, if I transform an instance of class A to the XML, I will have all its fields (id) and the referenced B class fields (id, field1, field2) like this:

<a>
    <id>2</id>
    <b>
        <id>5</id>
        <field1>test1</field1>
        <field2>test3</field2>
    </b>
</a>

Is is possible to modify what fields from referenced class B are included in the XML of the A class? E.g. I want to say that when I transform an instance of A class, I just want to get id from the B class (no field1 and field2 fields), so I want to get:

<a>
    <id>2</id>
    <b>
        <id>5</id>
    </b>
</a>

I don't want to permanently annotate the B class (using @XMLTransient or @XMLElement) to achieve it, as there are cases in which I want to export whole B class as is (with id, field1 and field2.)
I just don't want to export all these fields when the B class is referenced from A.

Is this even possible with JAX-B?


Solution 1:

You can use annotation @XmlTransient to ignore fields. Put this annotation on field itself or its getter.

Solution 2:

You can use @XmlTransient on the field. Also the default JAXB bindings can be overridden at a global scope or on a case-by-case basis as needed by using custom binding declarations.

Check out the Guide to JAXB from Baeldung website for more examples.

Solution 3:

Ok, I've come up with some hacky solution:

@XmlRootElement
public class A {

    private Long id;
    private B b;

    // setters and getters
}

I've provided an additional getter just for the REST use case, so it's like:

@XMLTransient
public B getB() {
    return b;
}

@XMLElement(name="b")
public Long getBForREST() {
    return b.getId();
}

It results in the following structure:

<a>
    <id>2</id>
    <b>5</b>
</a>

It's not exactly same structure I aimed for it works for me.

I don't like this solution - an @XMLExclude({"field1", "field2"}) or something like that would be much cleaner in my opinion.

Nevertheless - for now on, it works; it's ugly, but it works.