有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javajaxb列表作为顶级XML

更新:最终,我尝试了这里建议的一切,似乎取得了一些进展,但我的API设计过度,无法达到预期目的,因此我在GET/student调用的字符串响应中切换到硬编码“student list”,这足以证明我需要它

我正在开发一个简单的REST服务,它使用XML处理学生记录

当我做一个“上车/学生”时,我得到:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<students>
    <student>
        <grade>B</grade>
        <name>Jane</name>
    </student>
    ...
</students>

但是,我希望输出为:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student-list>
    <student>
        <grade>B</grade>
        <name>Jane</name>
    </student>
    ...
</student-list>

这是我的学生。java代码片段:

@XmlRootElement(name = "student")
public class Student {
    private String name;
    private String grade;

    public Student() {
    }

    public Student(String name, String grade) {
        super();
        this.name = name;
        this.grade = grade;
    }

    // getters/setters ...

}

我尝试将XmlRootElement更改为“student list”,但这会使列表的每个子元素都成为student list类型,并忽略顶级元素列表

该项目将JAX-RS与StudentsResource类一起使用,我已尝试在该资源类上设置XmlRootElement名称,但这并不影响任何输出

它似乎是根据StudentsResource类自动命名顶级列表,我不知道如何覆盖这个名称

我一直在梳理这方面的文档,但Java不是我这些天最强大的语言,所以我很难理解JAXB和JAX-RS的各个部分是如何组合在一起的

有什么想法,或是朝着正确的方向推进

编辑:添加学生资源。java代码片段:

@Path("/student")
public class StudentsResource {
    // this is a mapper class
    @Context
    UriInfo uriInfo;
    @Context
    Request request;

    StudentService studentService;

    public StudentsResource() {
        studentService = new StudentService();
    }

    @GET
    @Produces("text/xml;charset=utf-8")
    public List<Student> getStudents() {
        return studentService.getStudentAsList();
    }
    ...        
}

根据Mateen Momin的反馈,我现在在GET/student上有REST服务的输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<studentDao_Students>
    <student>
        <name>Jane</name>
        <grade>B</grade>
    </student>
    ...
</studentDao_Students>

我有一个StudentDao,它由StudentService包装,最终由资源类调用,以使HTTP调用成为可能。我已经将我的学生类移到了StudentDao中,这使我意识到StudentService实际上是被编组的,下面是更新的片段:

学生道。java

public enum StudentDao {
    instance;
    private Map<String, Student> students = new HashMap<String, Student>();

    private StudentDao() {

        //pre-populate for testing purposes
        Student student = new Student("John", "A");
        students.put("John", student);
        student = new Student("Jane", "B");
        students.put("Jane", student);
        student = new Student("TESTUSER", "F");
        students.put("TESTUSER", student);
    }

    public Map<String, Student> getStudents() {
        return students;
    }

    @XmlRootElement(name="student")
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Student {
        private String name;
        private String grade;

        public Student() {
        }

        public Student(String name, String grade) {
            super();
            this.name = name;
            this.grade = grade;
        }
        // getters/setters here...
    }
}

学生服务。java

@XmlRootElement(name = "student-list")
@XmlAccessorType(XmlAccessType.FIELD)
public class StudentService {

    StudentDao studentDao;

    public StudentService() {
        studentDao = StudentDao.instance;
    }
    // CRUD methods here which call the StudentDao HashMap
}

学生资源。java

@Path("/student")
public class StudentsResource {
    @Context
    UriInfo uriInfo;
    @Context
    Request request;

    StudentService studentService;

    public StudentsResource() {
        studentService = new StudentService();
    }

    @GET
    @Produces("text/xml;charset=utf-8")
    public List<Student> getStudents() {
        return studentService.getStudentAsList();
    }

    // other HTTP calls, POST,PUT,etc. here        
}

我创建了一个main函数,以查看如果指定JAXBContext会发生什么:

主要用于测试控制台输出

public class Main {
    public static void main(String[] args) {
        StudentService studentDao = new StudentService();        

        StudentDao.Student stu1 = new StudentDao.Student();
        stu1.setName("marc");
        stu1.setGrade("A");
        StudentDao.Student stu2 = new StudentDao.Student();
        stu2.setName("jacob");
        stu2.setGrade("B");
        StudentDao.Student stu3 = new StudentDao.Student();
        stu3.setName("anthony");
        stu3.setGrade("A");

        studentDao.createStudent(stu1);
        studentDao.createStudent(stu2);
        studentDao.createStudent(stu3);


        try {

            File file = new File("out.xml");
            JAXBContext jaxbContext = JAXBContext.newInstance(StudentService.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            // output pretty printed
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            jaxbMarshaller.marshal(studentDao, file);
            jaxbMarshaller.marshal(studentDao, System.out);

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}

当我运行这个main函数来查看输出时,我实际上得到了这样的结果,当然,这与其余的输出不匹配:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student-list>
    <studentDao>instance</studentDao>
</student-list>

这似乎很有希望,但我无法在REST调用中覆盖顶级类名,这正是我最终需要的

还有其他关于我做错了什么的想法吗


共 (1) 个答案

  1. # 1 楼答案

    学生班

    import java.util.ArrayList;
    
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlRootElement;
    
    
    @XmlRootElement(name = "student-list")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Students{
    //students
        @XmlElement(name = "student")
        public ArrayList<Student> studentsLst;
    
        //getters and setters
        public ArrayList<Student> getStudentsLst() {
            return studentsLst;
        }
    
        public void setStudentsLst(ArrayList<Student> studentsLst) {
            this.studentsLst = studentsLst;
        }
    
        @XmlRootElement
        @XmlAccessorType(XmlAccessType.FIELD)
        public static class Student {
            private String name;
            private String grade;
    
            public Student() {
            }
    
            public Student(String name, String grade) {
                super();
                this.name = name;
                this.grade = grade;
            }
    
            // getters/setters ...
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public String getGrade() {
                return grade;
            }
    
            public void setGrade(String grade) {
                this.grade = grade;
            }
    
        }
    
    }
    

    主要方法/marshaller使用:

    public static void main(String[] args) {
            Students.Student stu1 = new Students.Student();
            stu1.setName("marc");
            stu1.setGrade("A");
            Students.Student stu2 = new Students.Student();
            stu2.setName("jacob");
            stu2.setGrade("B");
            Students.Student stu3 = new Students.Student();
            stu3.setName("anthony");
            stu3.setGrade("A");
    
            ArrayList<Students.Student> studentsLst = new ArrayList<>();
            studentsLst.add(stu1);
            studentsLst.add(stu2);
            studentsLst.add(stu3);
    
            Students students = new Students();
    
            students.setStudentsLst(studentsLst);
    
    
            try {
    
                File file = new File("C:\\file.xml");
                JAXBContext jaxbContext = JAXBContext.newInstance(Students.class);
                Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    
                // output pretty printed
                jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    
                jaxbMarshaller.marshal(students, file);
                jaxbMarshaller.marshal(students, System.out);
    
                  } catch (JAXBException e) {
                e.printStackTrace();
                  }
    }
    

    生成的输出:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <student-list>
        <student>
            <name>marc</name>
            <grade>A</grade>
        </student>
        <student>
            <name>jacob</name>
            <grade>B</grade>
        </student>
        <student>
            <name>anthony</name>
            <grade>A</grade>
        </student>
    </student-list>
    

    PS:由于您使用的是REST,上述主要方法可用于您的FYI。使用这个main方法来相应地构建studentService.getStudentAsList()方法。(我的假设是,它将给出几乎相同的xml。):)