I have a Java bean ala
@XmlRootElement public class Bean {
@XmlElementWrapper(name = "ints") @XmlElement(name = "int")
int[] values;
// constructors, getters, setters, etc...
}
JAXB is producing XML like
<bean>
<ints>
<int>12</int>
<int>34</int>
<int>56</int>
</ints>
</bean>
I would like the array indices to be included on the <int>
tags as array position conveys important value. Preferably as attributes like
<bean>
<ints>
<int id='0'>12</int>
<int id='1'>34</int>
<int id='2'>56</int>
</ints>
</bean>
Is there a way to do this?
The order of XML elements does carry information. A sequence of elements has an explicit order, so adding an array index would be redundant, unless you plan on skipping indexes, or having them out-of-order.
Because of this reasoning, JAXB provides no way of doing what you're asking automatically. If you still want to do this, you'll need to wrap your values in a class which incorporates the index values as an @XmlAttribute
value:
@XmlRootElement
public class Bean {
@XmlElementWrapper(name = "ints")
@XmlElement(name = "int")
MyInt[] values;
// constructors, getters, setters, etc...
}
public class MyInt {
@XmlAttribute(name="id")
int id;
@XmlValue
int value;
}
It would up to you to make sure the id
fields are populated correctly.
You could also do this using an XmlAdapter
Change your Bean class to look like this:
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
public class Bean {
@XmlElement(name = "ints")
@XmlJavaTypeAdapter(IndexAdapter.class)
int[] values;
}
The @XmlJavaTypeAdapter allows you to convert a property into another object that JAXB will marshal. This is similar to what was suggested above, without requiring your model to change. The adapter would look like:
import javax.xml.bind.annotation.adapters.XmlAdapter;
import forum.AdaptedArray.AdaptedArrayValue;
public class IndexAdapter extends XmlAdapter<AdaptedArray, int[]>{
@Override
public AdaptedArray marshal(int[] v) throws Exception {
AdaptedArray adaptedArray = new AdaptedArray();
for(int x=0; x<v.length; x++) {
adaptedArray.addValue(x, v[x]);
}
return adaptedArray;
}
@Override
public int[] unmarshal(AdaptedArray v) throws Exception {
int[] intArray = new int[v.ints.size()];
for(AdaptedArrayValue adaptedArrayValue : v.ints) {
intArray[adaptedArrayValue.index] = adaptedArrayValue.value;
}
return intArray;
}
}
The adapted value class would look like:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlValue;
public class AdaptedArray {
@XmlElement(name="int")
List<AdaptedArrayValue> ints = new ArrayList<AdaptedArrayValue>();;
public void addValue(int index, int value) {
AdaptedArrayValue adaptedArrayValue = new AdaptedArrayValue();
adaptedArrayValue.index = index;
adaptedArrayValue.value = value;
ints.add(adaptedArrayValue);
}
public static class AdaptedArrayValue {
@XmlAttribute int index;
@XmlValue int value;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With