1

我目前有以下两个 POJO 类。

@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
    @XmlElement
    private String firstName;
    @XmlElement
    private String lastName;
    @XmlElement
    private String email;

    /* snipped getters, setters, and constructors. */
}


@XmlRootElement(name = "testobj")
@XmlAccessorType(XmlAccessType.FIELD)
public class TestObj {
    @XmlElement(name="data")
    private String someData;
    @XmlElement
    private User user;

    /* snipped getters, setters, and constructors. */
}

电流输出

<testObj>
    <name>testObj</name>
    <user>
        <firstName>John</firstName>
        <lastName>Doe</lastName>
        <email>john@doe.org</email>
    </user>
</testObj>

期望的输出

<testObj>
    <data>some data</data>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <email>john@doe.org</email>
</testObj>

有什么方法可以实现所需的输出?嵌套用户对象的基本原理是有这样的类型层次结构:

User
  |-> Customer
        |-> SpecialCustomer

DetailedUser
  |-> DetailedCustomer
        |-> DetailedSpecialCustomer

这六种类型专门用于保存将作为 API 调用结果输出的数据。他们没有逻辑。应用程序内部使用了另一组更复杂的类型,以及将内部应用程序类型转换为 api 输出类型的一组工厂。API 输出类型使用 JAXB 和 Jackson 序列化为 XML 和 JSON。为了避免重复代码,我想使用组合将简单的 User|Customer|SpecialCustomer 嵌入到复杂类型中,如下所示:

@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.FIELD)
public class DetailedUser {
    @Xml[...?]
    private User user;
    @XmlElement
    private String otherProperty;
    @XmlElement
    private String extraStuff;

    /* snipped getters, setters, and constructors. */
}

当通过 JAXB 输出DetailedUser 时,它应该如下所示:

<user>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <email>john@doe.org</email>
    <otherProperty>something</otherProperty>
    <extraStuff></extraStuff>
</user>

对象树将通过 Spring MVC 使用内容协商以适当的格式输出。

4

1 回答 1

2

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

你可以使用 MOXy 的@XmlPath(".")扩展:

测试对象

package forum10844319;

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name = "testobj")
@XmlAccessorType(XmlAccessType.FIELD)
public class TestObj {
    @XmlElement(name="data")
    private String someData;
    @XmlPath(".")
    private User user;

    /* snipped getters, setters, and constructors. */
}

用户

package forum10844319;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "user")
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
    @XmlElement
    private String firstName;
    @XmlElement
    private String lastName;
    @XmlElement
    private String email;

    /* snipped getters, setters, and constructors. */
}

jaxb.properties

要将 MOXy 指定为您的 JAXB 提供程序,您需要包含一个jaxb.properties在与您的域模型相同的包中调用的文件:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

演示

package forum10844319;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(TestObj.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum10844319/input.xml");
        TestObj testObj = (TestObj) unmarshaller.unmarshal(xml);

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

}

输入.xml/输出

<testobj>
    <data>some data</data>
    <firstName>John</firstName>
    <lastName>Doe</lastName>
    <email>john@doe.org</email>
</testobj>
于 2012-06-01T10:09:50.570 回答