Per Jernström
Per Jernström

Reputation: 21

Setup XStream to set object value to null if a certain attribute is present

I am receiving notifications in xml format from a third party system and trying to parse them with XStream.

Notification sent from third party system looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<account>
  <phone1>unknown</account_code>
  <phone2/>
  <phone3 nil="true"/>
</account>

An our java representation of the notification looks like this:

public class Account {
  private String phone1;  
  private String phone2; 
  private String phone3;
}

Out of the box XStream parses phone1 and phone2 as expected, but phone3 is of course also parsed to an empty string.

Is there a neat way to make XStream understand that when nil="true" that the value should be set to null?

Upvotes: 2

Views: 349

Answers (1)

hc_dev
hc_dev

Reputation: 9418

You could use a custom converter like explained in:

Custom Converter to parse attributes

Implement a custom Converter like this:

public class PhoneNilableConverter implements Converter {

    @Override
    public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) {
        // implement logic for marshalling to xml
        if (o == null) {
            writer.addAttribute("nil", "true");
        } else {
            writer.setValue(o.toString());
        }
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        String phone = "";  // default phone value

        if ("true".equals(reader.getAttribute("nil"))) {
            phone = null;
        } else {
            phone = reader.getValue();
        }

        return phone;
    }

    @Override
    public boolean canConvert(Class cls) {
        return cls == String.class;
    }
}

Then add the converter to your field with annotation @XStreamConverter like this:

public class Account {
  private String phone1;  
  private String phone2; 
  @XStreamConverter(value=PhoneNilableConverter.class)
  private String phone3;
}

Next you can test and make sure to enable XStream to processAnnotations for this class:

XStream xs = new XStream();
xs.processAnnotations(Account.class); // required to make XStream aware of annotations

Account a = (Account) xs.fromXML(
  "<account>\n" +
  "  <phone1>unknown</phone1>\n" +
  "  <phone2/>\n" +
  "  <phone3 nil="true"/>\n" +
  "</account>");
System.out.println(a);

See also:

Upvotes: 1

Related Questions