微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

jaxb – 如何使用错误的父/子模型解组xml消息

我试图将第三方XML有效负载解组到一个类中.问题是有效负载具有父/子关系,根节点,父节点和子节点都具有相同的元素名称.以下是有效负载的示例.
<?xml version="1.0" encoding="UTF-8"?>
<Directory>
    <id>2</id>
    <name>Media</name>
    <Directory>
        <id>5</id>
        <name>Default_Content</name>
        <Directory>
            <id>9</id>
            <name>Images</name>
        </Directory>
        <Directory>
            <id>8</id>
            <name>Icons</name>
        </Directory>
        <Directory>
            <id>6</id>
            <name>Additional_Content</name>
        </Directory>
    </Directory>
    <Directory>
        <id>12</id>
        <name>IC</name>
    </Directory>
</Directory>

所以我试图注释一个类,以便JAXB / JAX-RS可以将其解组为有用的东西.

我尝试过这样的事情

@XmlRootElement(name="Directory")
public class Directory {
    private int id;
    private String name;

    @XmlElement(name="Directory");
    private List<Directory> directories = new ArrayList<Directory>();
}

但是,可以预见的是,由于具有两个具有相同名称属性,它会抛出IllegalAnnotationException.

关于如何使用JAXB / JAX-RS干净地处理这个烂摊子的任何想法,或者我应该自己解析它?

简答

例外是由于字段/属性冲突.您可以注释属性(获取方法)或在类型上设置以下注释:

@XmlAccessorType(XmlAccesstype.FIELD)
public class Directory {
  ...
}

答案很长

JAXB的认访问类型是PUBLIC_MEMBER,这意味着JAXB将映射所有公共字段(实例变量)和属性(get / set方法).

public class Foo {

    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

如果您注释一个字段:

public class Foo {

    @XmlAttribute
    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

然后JAXB会认为它有两个bar属性映射并抛出异常:

Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "bar"
    this problem is related to the following location:
        at public java.lang.String example.Foo.getBar()
        at example.Foo
    this problem is related to the following location:
        at private java.lang.String example.Foo.bar
        at example.Foo

解决方案是注释属性并将XmlAccesstype类型设置为FIELD

@XmlAccessorType(XmlAccesstype.FIELD)
public class Foo {

    @XmlAttribute
    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

}

你的模特

目录

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccesstype;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Directory")
@XmlAccessorType(XmlAccesstype.FIELD)
public class Directory {
    private int id;
    private String name;

    @XmlElement(name="Directory")
    private List<Directory> directories = new ArrayList<Directory>();

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public List<Directory> getDirectories() {
        return directories;
    }

    public void setDirectories(List<Directory> directories) {
        this.directories = directories;
    }

}

演示

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(Directory.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Directory directory = (Directory) unmarshaller.unmarshal(new File("input.xml"));

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

}

原文地址:https://www.jb51.cc/xml/293107.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。