How to handle optional attribute with XStream

1.7k Views Asked by At

I would like to know how I can implement optional attributes within XStream.

Here is the XML:

<AttributeValues>
   <AttributeValue attributeId='id01' languageId='en'>20</AttributeValue>   
   <AttributeValue attributeId='id02'>99</AttributeValue>
   <AttributeValue attributeId='id03' languageId='en'78</AttributeValue>
   <AttributeValue attributeId='id04' languageId='en'>14</AttributeValue>
   <AttributeValue attributeId='id05'>9</AttributeValue>
</AttributeValues>

After the parsing process, not every 'AttributeValue' item has a languageId.

XStream sets such empty values to 'null'. But I would like to have it as an empty string "".

How do I implement this?

1

There are 1 best solutions below

0
On BEST ANSWER

You can achieve your goal using custom Converter class.

There will be a bit of guessing here since you haven't posted code for AttributeValues and AttributeValue class. I will use following classes:

AttributeValues class:

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

import java.util.ArrayList;
import java.util.List;

@XStreamAlias("AttributeValues")
public class AttributeValues
{
    @XStreamImplicit(itemFieldName="AttributeValue")
    public List<AttributeValue> Values;

    public AttributeValues()
    {
        Values = new ArrayList<AttributeValue>();
    }

    public void add(String id, String lg, String value)
    {
        AttributeValue item = new AttributeValue();
        item.attributeId = id;
        item.languageId = lg;
        item.value = value;
        Values.add(item);
    }
}

AttributeValue class:

import com.thoughtworks.xstream.annotations.XStreamAsAttribute;

public class AttributeValue
{
    @XStreamAsAttribute
    public String attributeId;
    @XStreamAsAttribute
    public String languageId;
    public String value;
}

And here is AttributeValueConverter class:

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class AttributeValueConverter implements Converter
{
    public boolean canConvert(Class clazz) {
        return AttributeValue.class == clazz;
    }

    public void marshal(Object object, HierarchicalStreamWriter hsw, MarshallingContext mc) {
        AttributeValue av = (AttributeValue) object;
        hsw.addAttribute("attributeId", av.attributeId);
        hsw.addAttribute("languageId", av.languageId);
        hsw.setValue(av.value);
    }

    public Object unmarshal(HierarchicalStreamReader hsr, UnmarshallingContext uc) {
        AttributeValue av = new AttributeValue();
        av.attributeId = hsr.getAttribute("attributeId");
        av.languageId = hsr.getAttribute("languageId");
        if (av.languageId == null) av.languageId = "";
        av.value = hsr.getValue();
        return av;
    }

}

Serialization:

    AttributeValues obj = new AttributeValues();
    obj.add("id01", "en", "20");

    XStream xstream = new XStream();
    xstream.autodetectAnnotations(true);
    xstream.registerConverter(new AttributeValueConverter());
    String s = xstream.toXML(obj);

Unserialization:

    XStream xstream = new XStream();
    xstream.autodetectAnnotations(true);
    xstream.registerConverter(new AttributeValueConverter());
    AttributeValues newobj = (AttributeValues)xstream.fromXML(s);