peer
peer

Reputation: 4719

Adding getter method inhibits parsing when value starts with digit

I want to unmarshal xml content like this:

JAXBContext context = JAXBContext.newInstance(Node.class);
        
String input = "<item><d>foo</d></item>";
StreamSource istream = new StreamSource(new StringReader(input));
JAXBElement<Node> node = context.createUnmarshaller().unmarshal(istream, Node.class);
System.out.println(node.getValue().toString());

The d element cannot be trivially converted into the desired object, here a Boolean, so I use a setter method for that.

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "item")
public class Node {

    @XmlElement(name = "d") 
    private Boolean value;

    public void setValue(String d) {
        this.value = d.equals("") ? Boolean.TRUE : Boolean.FALSE;
    }
        
    @Override
    public String toString() {
        
        return value.toString();
    }
}

The XmlAnnotaion can be at setValue as well however when I add a getter method it has to be at the field(otherwise there is no parse and value remains null).

public Boolean getValue() {return value;}

But if instead of foo the value starts with a digit or a special character, say ?, there is again no parse.

Summary of effects:

annotation at field + no getter -> parses foo
annotation at setter + no getter -> parses foo and 0foo
annotation at field + getter -> parses foo
annotation at setter + getter -> parses neither

How do I need do set the annotations so that I can parse arbitrary values in d and why does it work here for strings that start with a letter?

Upvotes: 0

Views: 85

Answers (1)

lscoughlin
lscoughlin

Reputation: 2416

Because XML is a typed language, and the types of the getter and setter need to match.

If. this is like, a real thing you're getting paid to do then you need to go and spend some time reading the jaxb documentation and probably the xml schema documentation.

here's some code because why not.

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "item")
public class Node {

    private Boolean value;

    @XmlElement(name = "d", nillable = true, required = false)
    public void setValue(String d) {
        this.value = "".equals(d) ? Boolean.TRUE : Boolean.FALSE;
    }

    public String getValue(String d) {
        return String.valueOf(value);
    }

    public boolean isValue() {
        return Boolean.TRUE.equals(value);
    }

    @Override
    public String toString() {
        return "[Node|value=" + value + "]";
    }

    public static void main(String... args) {
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(Node.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Node node = (Node) jaxbUnmarshaller.unmarshal(new StringReader("<item><b></b></item>"));
            System.out.println(node);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

Upvotes: 0

Related Questions