【问题标题】:JAXB - Suppress Boolean attribute if falseJAXB - 如果为 false,则禁止布尔属性
【发布时间】:2011-07-01 20:07:03
【问题描述】:

假设我有一堂课

@XmlRootElement(name="thing")
public class Thing{
    private String name;
    private boolean awesome;

    @XmlValue public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.value;
    }


    @XmlAttribute public void setAwesome(boolean awesome) {
        this.awesome = awesome;
    }
    public boolean isAwesome() {
        return this.awesome;
    }
}

如果我创建一些东西,然后将它们编组为 XML,它看起来像这样:

飞行忍者:

<thing awesome="true">flying ninja</thing>

一个普通的旧爆米花球:

<thing awesome="false">popcorn ball</thing>

但是...我想做的是改变我的布尔属性编组的方式。我宁愿看到爆米花球长成这样,压制了awesome属性:

<thing>popcorn ball</thing>

我该怎么做?

非常感谢!

【问题讨论】:

    标签: java xml jaxb marshalling


    【解决方案1】:

    注意:我是 EclipseLink JAXB (MOXy) 负责人,也是 JAXB 2.X (JSR-222) 专家组的成员。

    使用 MOXy,您可以按照 Hovercraft Full Of Eels 的建议执行 XmlAdapter 方法。它看起来像:

    布尔适配器

    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class BooleanAdapter extends XmlAdapter<Boolean, Boolean> {
    
        @Override
        public Boolean unmarshal(Boolean v) throws Exception {
            return Boolean.TRUE.equals(v);
        }
    
        @Override
        public Boolean marshal(Boolean v) throws Exception {
            if(v) {
                return v;
            }
            return null;
        }
    
    }
    

    事物

    您使用@XmlJavaTypeAdapter 注释将您的属性与XmlAdapter 相关联,如下所示:

    import javax.xml.bind.annotation.XmlAttribute;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlValue;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @XmlRootElement(name="thing")
    public class Thing{
        private String name;
        private boolean awesome;
    
        @XmlValue public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
    
    
        @XmlAttribute
        @XmlJavaTypeAdapter(BooleanAdapter.class)
        public void setAwesome(boolean awesome) {
            this.awesome = awesome;
        }
        public boolean isAwesome() {
            return this.awesome;
        }
    }
    

    演示

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Thing.class);
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    
            Thing thing = new Thing();
            thing.setName("popcorn ball");
    
            thing.setAwesome(false);
            marshaller.marshal(thing, System.out);
    
            thing.setAwesome(true);
            marshaller.marshal(thing, System.out);
        }
    
    }
    

    输出

    <?xml version="1.0" encoding="UTF-8"?>
    <thing>popcorn ball</thing>
    <?xml version="1.0" encoding="UTF-8"?>
    <thing awesome="true">popcorn ball</thing>
    

    使用 JAXB RI

    如果您使用 JAXB RI 运行此示例,您将收到以下异常:

    Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
    Adapter example.BooleanAdapter is not applicable to the field type boolean. 
        this problem is related to the following location:
            at @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(type=class javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter$DEFAULT, value=class example.BooleanAdapter)
            at public boolean example.Thing.isAwesome()
            at forum251.Thing
    

    更多信息

    【讨论】:

    • 遗憾的是它在 RI 中不起作用。但你的回答非常彻底,让我找到了合适的解决方案。谢谢。
    • 如果您稍微更改方法签名以使用 Boolean 而不是 boolean,它确实可以在 JAXB RI 中使用。至少对于吸气剂,这种方法对我有用。我没有像你的例子那样用二传手测试它。
    【解决方案2】:

    通过使用可为空的类型并向您的类注册一个 JAXB 侦听器来实现此目的。在 JAXB 侦听器中,如果您不想编组它,请将您的属性设置为 null。这种方法应该适用于任何 JAXB 实现。

    您的(布尔值或其他)属性

    @XmlAttribute(required = false)
    private Boolean valueUnknown;
    

    JAXB beforeMarshal 处理程序

    @SuppressWarnings("PMD")
    private void beforeMarshal(final Marshaller marshaller) {
        // Remove the "valueUnknown" attribute if it is not true.
        // Assigning a null value implies that the attribute is removed.
        if(!valueUnknown) {
            valueUnknown = null;
        }
    }
    

    这种方法可以 - 例如 - 产生以下结果。注意 valueUnknown 属性只有在没有给出 value 属性时才会出现。

        <items>
            <item xsi:type="eduDataExchange:compoundValue" valueUnknown="true"/>
            <item xsi:type="eduDataExchange:compoundValue" value="4" percentage="3"/>
        </items>
    

    【讨论】:

      【解决方案3】:

      我(还)不熟悉 JAXB,但通常这种事情对于 XSLT processing 或转换应该是完全可行的。

      此外,这个问题的答案提到了使用 XmlAdapter 看起来可以直接适用于您的问题:How to let JAXB render boolean as 0 and 1, not true and false

      【讨论】:

        【解决方案4】:

        用布尔对象替换布尔值,它为我解决了这个问题。

        使用:-

        private Boolean awesome;
        

        而不是:-

        private boolean awesome;
        

        【讨论】:

        • 是的,但这很糟糕,因为我不希望“null”成为我代码中其他任何地方的选项。
        猜你喜欢
        • 2017-11-05
        • 2019-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        相关资源
        最近更新 更多