首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从JAXB泛型中删除xsi:type、xmlns:xs和xmlns:xsi

从JAXB泛型中删除xsi:type、xmlns:xs和xmlns:xsi
EN

Stack Overflow用户
提问于 2012-06-25 23:44:17
回答 3查看 18K关注 0票数 5

在使用JAXB时,我希望在使用泛型时从XML元素中删除多余的名称空间/类型。我怎么能做到这一点,或者我做错了什么?我喜欢使用泛型,这样我只需要写一次代码块。

示例代码:

代码语言:javascript
复制
public static void main(String[] args) {
    try {
        TestRoot root = new TestRoot();
        root.name.value = "bobby";
        root.age.value = 102;
        root.color.value = "blue";

        JAXBContext context = JAXBContext.newInstance(root.getClass());
        Marshaller marsh = context.createMarshaller();
        marsh.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
        marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        marsh.marshal(root,pw);
        System.out.println(sw.toString());
    }
    catch(Throwable t) {
        t.printStackTrace();
    }
}

@XmlRootElement
static class TestRoot {
    @XmlElement public TestGeneric<String> name = new TestGeneric<String>(true);
    @XmlElement public TestGeneric<Integer> age = new TestGeneric<Integer>(true);
    @XmlElement public TestWhatIWouldLike color = new TestWhatIWouldLike(true);
}

@XmlAccessorType(XmlAccessType.NONE)
static class TestGeneric<T> {
    @XmlAttribute public boolean isRequired;
    @XmlElement public T value;

    public TestGeneric() {
    }

    public TestGeneric(boolean isRequired) {
        this.isRequired = isRequired;
    }
}

@XmlAccessorType(XmlAccessType.NONE)
static class TestWhatIWouldLike {
    @XmlAttribute public boolean isRequired;
    @XmlElement public String value;

    public TestWhatIWouldLike() {
    }

    public TestWhatIWouldLike(boolean isRequired) {
        this.isRequired = isRequired;
    }
}

输出:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testRoot>
    <name isRequired="true">
        <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">bobby</value>
    </name>
    <age isRequired="true">
        <value xsi:type="xs:int" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">102</value>
    </age>
    <color isRequired="true">
        <value>blue</value>
    </color>
</testRoot>
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-06-26 04:55:38

测试通用

您的JAXB (JSR-222)实现将为每个类(即TestGeneric,而不是类型(即TestGeneric<Integer>) )创建映射。因此,它将把value字段视为Object类型。这将产生xsi:type属性,因为您的JAXB实现添加了足够的信息来解组相同的类型。

代码语言:javascript
复制
@XmlAccessorType(XmlAccessType.NONE)
static class TestGeneric<T> {
    @XmlAttribute public boolean isRequired;
    @XmlElement public T value;

    public TestGeneric() {
    }

    public TestGeneric(boolean isRequired) {
        this.isRequired = isRequired;
    }
}

演示

下面是一种你可以使用的方法。我引入了TestGeneric的子类来表示不同的可能类型。

代码语言:javascript
复制
package forum11192623;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;

public class Demo {

    public static void main(String[] args) {
        try {
            TestRoot root = new TestRoot();
            root.name.value = "bobby";
            root.age.value = 102;
            root.color.value = "blue";

            JAXBContext context = JAXBContext.newInstance(root.getClass());
            Marshaller marsh = context.createMarshaller();
            marsh.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
            marsh.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);

            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            marsh.marshal(root,pw);
            System.out.println(sw.toString());
        }
        catch(Throwable t) {
            t.printStackTrace();
        }
    }

    @XmlRootElement
    static class TestRoot {
        @XmlElement public TestString name = new TestString(true);
        @XmlElement public TestInteger age = new TestInteger(true);
        @XmlElement public TestString color = new TestString(true);
    }

    @XmlAccessorType(XmlAccessType.NONE)
    @XmlTransient
    @XmlSeeAlso({TestInteger.class, TestString.class})
    static class TestGeneric<T> {
        @XmlAttribute 
        public boolean isRequired;
        public T value;

        public TestGeneric() {
        }

        public TestGeneric(boolean isRequired) {
            this.isRequired = isRequired;
        }
    }

    static class TestInteger extends TestGeneric<Integer> {
        public TestInteger() {
        }
        public TestInteger(boolean b) {
            super(b);
        }
        @XmlElement
        public Integer getValue() {
            return value;
        }
        public void setValue(Integer value) {
            this.value = value;
        }
    }

    static class TestString extends TestGeneric<String> {
        public TestString() {
        }
        public TestString(boolean b) {
            super(b);
        }
        @XmlElement
        public String getValue() {
            return value;
        }
        public void setValue(String value) {
            this.value = value;
        }
    }

}
票数 2
EN

Stack Overflow用户

发布于 2017-12-15 03:54:28

我可以在属性上使用@XmlAnyElement(lax=true),因为泛型参数导致了问题,然后必须在正在编组的实际类上添加@XmlRootElement,然后声明就消失了!太棒了!

票数 3
EN

Stack Overflow用户

发布于 2015-12-07 16:35:11

我得到了同样的问题,并根据Programmatically determine if a JAXB annotation will result in a xsi:type annotation?的建议解决了它

只需在泛型类对象上使用@XmlAnyElement(lax=true)而不是@XmlElement (本例中的值)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11192623

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档