当前位置: 首页 > 知识库问答 >
问题:

为什么Jackson序列化为XML的名称空间结构不正确

斜成济
2023-03-14

我试图使用Jackson的XMLMapper将对象序列化为XML。我希望它在适当的区域有名称空间。然而,当我序列化对象时,每个属性都有一个名称空间--直接属于我试图序列化的类的属性将有一个xmlns=“”,被引用类上的每个属性都包含它们自己的名称空间前缀(而不是整个被引用类的单个前缀)。

我用的是杰克逊2.9.8

我要序列化的主类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
        "name",
        "objectDescription",
        "exampleFieldClass"
})
@XmlRootElement(name = "ExampleClass", namespace = "urn:ExampleClass.dto")
public class ExampleClass
{

    @XmlElementRef(name = "name", namespace = "urn:ExampleClass.dto", type = JAXBElement.class, required = false)
    protected JAXBElement<String> name;
    @XmlElementRef(name = "objectDescription", namespace = "urn:ExampleClass.dto", type = JAXBElement.class, required = false)
    protected JAXBElement<String> objectDescription;
    @XmlElementRef(name = "exampleFieldClass", namespace = "urn:ExampleFieldClass.dto", type = JAXBElement.class, required = false)
    protected JAXBElement<ExampleFieldClass> ExampleFieldClass;

    public JAXBElement<String> getName() {
        return name;
    }

    public void setName(JAXBElement<String> name) {
        this.name = name;
    }

    public JAXBElement<String> getObjectDescription() {
        return objectDescription;
    }

    public void setObjectDescription(JAXBElement<String> objectDescription) {
        this.objectDescription = objectDescription;
    }

    public JAXBElement<ExampleFieldClass> getExampleFieldClass() {
        return ExampleFieldClass;
    }

    public void setExampleFieldClass(JAXBElement<ExampleFieldClass> ExampleFieldClass) {
        this.ExampleFieldClass = ExampleFieldClass;
    }
}

一种特殊类型:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExampleFieldClass", namespace = "urn:ExampleFieldClass.dto", propOrder = {
        "id", "dtoType"
})
public class ExampleFieldClass {

    @XmlElement(name = "id", namespace = "urn:ExampleFieldClass.dto")
    protected String id;
    @XmlElement(name = "dtoType", namespace = "urn:ExampleFieldClass.dto")
    protected String dtoType;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getDtoType() {
        return dtoType;
    }

    public void setDtoType(String dtoType) {
        this.dtoType = dtoType;
    }
}

XmlMapper配置和测试

public class ExampleTest {

    private final ExampleObjectFactory factory = new ExampleObjectFactory();

    @Test
    public void testSerialize() throws Exception {
        XmlMapper mapper = getXmlMapper();

        ExampleFieldClass exampleFieldClass = new ExampleFieldClass();
        exampleFieldClass.setDtoType("dtoType");
        exampleFieldClass.setId("id");

        ExampleClass exampleClass = new ExampleClass();
        exampleClass.setName(factory.createExampleClassName("name"));
        exampleClass.setObjectDescription(factory.createExampleClassObjectDescription("description"));
        exampleClass.setExampleFieldClass(factory.createExampleClassExampleFieldClass(exampleFieldClass));

        String serialized = mapper.writeValueAsString(exampleClass);
        System.out.println(serialized);
    }

    private XmlMapper getXmlMapper() {
        JacksonXmlModule module = new JacksonXmlModule();
        module.addSerializer(JAXBElement.class, new JsonSerializer<JAXBElement>() {
            @Override
            public void serialize(JAXBElement value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                if (value.isNil()) {
                    gen.writeNull();
                } else {
                    gen.writeObject(value.getValue());
                }
            }
        });

        XmlMapper objectMapper = new XmlMapper(module);
        objectMapper.registerModule(new JaxbAnnotationModule());

        objectMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        return objectMapper;
    }

    @XmlRegistry
    public static class ExampleObjectFactory {

        @XmlElementDecl(namespace = "urn:ExampleClass.dto", name = "name", scope = ExampleClass.class)
        public JAXBElement<String> createExampleClassName(String value) {
            QName _ExampleClassName_QNAME = new QName("urn:ExampleClass.dto", "name");
            return new JAXBElement<>(_ExampleClassName_QNAME, String.class, ExampleClass.class, value);
        }

        @XmlElementDecl(namespace = "urn:ExampleClass.dto", name = "objectDescription", scope = ExampleClass.class)
        public JAXBElement<String> createExampleClassObjectDescription(String value) {
            QName _ExampleClassObjectDescription_QNAME = new QName("urn:ExampleClass.dto", "objectDescription");
            return new JAXBElement<>(_ExampleClassObjectDescription_QNAME, String.class, ExampleClass.class, value);
        }

        @XmlElementDecl(namespace = "urn:ExampleFieldClass.dto", name = "ExampleFieldClass", scope = ExampleFieldClass.class)
        public JAXBElement<ExampleFieldClass> createExampleClassExampleFieldClass(ExampleFieldClass value) {
            QName _ExampleClassExampleFieldClass_QNAME = new QName("urn:ExampleFieldClass.dto", "ExampleFieldClass");
            return new JAXBElement<>(_ExampleClassExampleFieldClass_QNAME, ExampleFieldClass.class, ExampleClass.class, value);
        }
    }
}

实际的XML输出如下:

<?xml version='1.0' encoding='UTF-8'?>
<ExampleClass xmlns="urn:ExampleClass.dto">
    <name xmlns="">name</name>
    <objectDescription xmlns="">description</objectDescription>
    <exampleFieldClass xmlns="">
        <wstxns1:id xmlns:wstxns1="urn:ExampleFieldClass.dto">id</wstxns1:id>
        <wstxns2:dtoType xmlns:wstxns2="urn:ExampleFieldClass.dto">dtoType</wstxns2:dtoType>
    </exampleFieldClass>
</ExampleClass>

不应该在每个属性上定义名称空间,也不应该将名称空间定义为空字符串。

需要注意的是:如果将属性注释更改为@XMLElement,空名称空间xmlns=“”将不存在;但是,它将不再正确处理JaxbElement(空vs null)。

有人知道我做错了什么吗?

共有1个答案

辛意智
2023-03-14

如果更改ExampleClass的定义:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
        "name",
        "objectDescription",
        "exampleFieldClass"
})
@XmlRootElement(name = "ExampleClass", namespace = "urn:ExampleClass.dto")
public class ExampleClass
{
    
    @XmlElement(name = "name", namespace = "urn:ExampleClass.dto", required = false)
    protected String name;
    
    @XmlElement(name = "objectDescription", namespace = "urn:ExampleClass.dto", required = false)
    protected String objectDescription;
    
    @XmlElement(name = "exampleFieldClass", namespace = "urn:ExampleFieldClass.dto", required = false)
    protected ExampleFieldClass ExampleFieldClass;

}

并更改ExampleClass实例的创建:

    XmlMapper mapper = getXmlMapper();

    ExampleFieldClass exampleFieldClass = new ExampleFieldClass();
    exampleFieldClass.setDtoType("dtoType");
    exampleFieldClass.setId("id");

    ExampleClass exampleClass = new ExampleClass();
    exampleClass.setName("name");
    exampleClass.setObjectDescription("description");
    exampleClass.setExampleFieldClass(exampleFieldClass);

    String serialized = mapper.writeValueAsString(exampleClass);

产出将是:

<?xml version='1.0' encoding='UTF-8'?>
<ExampleClass xmlns="urn:ExampleClass.dto">
  <name>name</name>
  <objectDescription>description</objectDescription>
  <wstxns1:exampleFieldClass xmlns:wstxns1="urn:ExampleFieldClass.dto">
    <wstxns1:id>id</wstxns1:id>
    <wstxns1:dtoType>dtoType</wstxns1:dtoType>
  </wstxns1:exampleFieldClass>
</ExampleClass>
 类似资料:
  • 我的代码生成的名称空间有问题。我想要的是以下XML: 我得到的是以下XML: 主要区别是: 目前我正在做的是替换1中序列化字符串中的值 这是我正在使用的代码,我如何更改GetNameSpace()来做我在第1点中需要的事情

  • 我一直在阅读关于Jackson XML反序列化的教程(#1,#2)。我试图通过编写一些java代码来遵循示例: 根据教程,这将产生以下输出: 但是,它会导致以下错误输出: 属性顺序不正确,“id”字段包含不正确的XML元素,“note”字段包含不正确。据说,各种java注释应该会改变Jackson的行为,但似乎所有注释都被忽略了。有人知道这是为什么吗? 这是jackson xml databind

  • 为什么我得到一个空的输出?当我删除xml中的xmlns部分时,输出是预期的,但是intellisense不再工作了。 仓库xml 仓库xsl

  • 我有一个JSON字符串,它将空列表标记为而不是。因此,例如,如果我有一个没有子对象的对象,我将收到这样的字符串: 我想将其反序列化为父类,将子类正确设置为子类的空列表。 对于上面的JSON字符串,我想要一个将其id设置为13的对象,并将子元素设置为新的ArrayList 我知道如何为整个类使用注释 然后呢 但是,我想解决从字符串正确实例化列表的一般问题: 我能得到这样的东西吗?

  • 我正在使用Jackson XML 2.8.9,不幸的是,我找不到任何方法将空/空集合序列化为空节点。 负责序列化为XML的方法: 我尝试使用: > 序列化提供程序: Jackson 2.9.0 EMPTY_ELEMENT_AS_NULL功能: 不幸的是,什么都不管用。有人知道如何实现它吗? 试验方法: ReportView类: 我用示例代码准备了一个存储库:https://github.com/a

  • Jackson jax-rs内容提供程序用于我们基于jax-rs的REST API项目,以处理json和xml内容类型。作为对POJO的响应,我们有映射结构,我们的要求是将此映射结构序列化为XML中的List和JSON格式的Map。(映射键包含空格,因此不可能将这些键转换为XML元素名称)。为了实现这一点,我们实现了一个自定义的XML序列化程序... JSON: XML: 属性地图序列化r: JA