解组时,Jax-b解释得太多了

时间:2011-10-24 13:38:47

标签: java xml jaxb unmarshalling jaxb2

我有一个名为a的布尔字段和两个方法void setA(String a)boolean isA()。我已设置@XmlAccessorType(XmlAccessType.NONE)并使用@XmlAttribute作为设置者。

因为getter返回一个布尔值,但是setter期望一个字符串JAX-B只是忽略了这个setter。这是代码中各种错误的原因,因为布尔值设置不正确,调试非常烦人。

有没有办法告诉JAX-B使用setter?为什么JAX-B完全被getter方法搞糊涂了,我使用XmlAccessType.NONE会阻止所有隐式解释?

如果出现这样一个星座,计划B将让JAX-B失败,但是如何做到这一点?

感谢任何提示: - )

2 个答案:

答案 0 :(得分:3)

鉴于你已经在使用XmlAccessorType注释,我猜你已经知道你可以使用@XmlAccessType.FIELD并让JAXB在决定编组/解组的时候查看类字段而不是setter方法?

对于您当前的配置,您可能在setter方法上有@XmlElement注释,其中数据类型错误,如提及的评论者所述。从你的问题中不清楚你为什么需要setA取一个String而不是boolean参数,但如果你可以在setter上将类型更改为boolean,那么这也有效。

编辑:

根据您在下面的评论,您似乎有两种选择:

撰写@XmlAdapter

为字符串字段创建一个setter / getter对,为一个计算字段创建一个isA(这是我一直这样做的方式,因为它看起来有点简单):

String a;

void setA(String);
String getA();

// calcualted field:
boolean isA() {
    // or whatever your real implementation is
    return a.equals("yes"); 
}

答案 1 :(得分:2)

我建议Kevin建议使用@XmlAccessType.FIELD并结合XmlAdapter来获取您正在寻找的行为:

<强>根

要使此示例与JAXB-RI一起使用,我需要创建Boolean类型的字段。如果您使用的是EclipseLink JAXB (MOXy),则可以填写boolean字段。

package forum7876493;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Root {

    @XmlAttribute
    @XmlJavaTypeAdapter(BooleanAdapter.class)
    private Boolean a;

    public boolean isA() {
        return a;
    }

    public void setA(String s) {
        this.a = "yes".equals(s) || "on".equals(s) || "in".equals(s);
    }

}

<强> BooleanAdapter

XmlAdapter是您可以在setA(String)方法中添加逻辑的地方。

package forum7876493;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class BooleanAdapter extends XmlAdapter<String, Boolean> {

    @Override
    public Boolean unmarshal(String s) throws Exception {
        return "yes".equals(s) || "on".equals(s) || "in".equals(s);
    }

    @Override
    public String marshal(Boolean b) throws Exception {
        if(b) {
            return "yes";
        }
        return "no";
    }

}

<强>演示

package forum7876493;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root root = (Root) unmarshaller.unmarshal(new File("src/forum7876493/input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

<强> input.xml中

<?xml version="1.0" encoding="UTF-8"?>
<root a="on"/>

<强>输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root a="yes"/>

<强>更新

或者,您可以为String属性引入a getter。您需要将isA()方法设为@XmlTransient

package forum7876493;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement
public class Root {

    private boolean a;

    @XmlTransient
    public boolean isA() {
        return a;
    }

    @XmlAttribute
    public String getA() {
        if(a) {
            return "yes";
        }
        return "no";
    }

    public void setA(String s) {
        this.a = "yes".equals(s) || "on".equals(s) || "in".equals(s);
    }

}