繁体   English   中英

JAXB XMLAdapter:有没有办法将此方法转换为 JAXB XmlAdapter

[英]JAXB XMLAdapter: Is there a way to convert this method into JAXB XmlAdapter

我有一个 JSON 文件,我正在尝试使用JAXB注释方法将其转换为XML 现在一切正常,我能够将JSON转换为XML 现在我正在尝试稍微重构代码,以便我的 class 看起来干净。 因此,我正在尝试删除class中存在的方法,并将其设置为JAXB XMLAdapter ,以便其他类可以重用它。

基本上我想将XMLSupport方法从CarInfo class 移动到XMLAdapter 当我将CarInfo对象移动到XMLAdapter时,我不确定如何填充它们。

以下是我的JSON文件(为简单起见,已对其进行了修改):

{
   "brand": "Ferari",
   "build": "Italy",
    "engine": "Mercedes",
    "year": "2021"
   
}

Following is the XML that I expect JAXB to provide: (Observe the carInfo tag which is not present in JSON but I need in XML to match the standard XSD )

<?xml version="1.0"?>
<Car>
    <brand>Ferari</brand>
    <build>Italy</build>
    <carinfo>
        <engine>Mercedes</engine>
        <year>2021</year>
    </carinfo>
</Car>

以下是我拥有的课程:(与 JSON 元素匹配的Car class)

@XmlAccessorType(XmlAccessType.FIELD)
@XmlTransient
@XmlSeeAlso({MyCar.class});
public class Car{
    private String brand;
    private String build;
    
    @XmlTransient
    private String engine;

    @XmlTransient
    private String year;

    //Getter, Setters and other consturctiores ommited
}

以下是通过添加MYCar标签构建XMLcarInfo

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Car")
@XmlType(name = "Car", propOrder = {"brand","build", "carInfo"})
public class MyCar extends Car{
    
    @XmlElement(name="carInfo")
    private CarInfo carInfo;
    
    public MyCar xmlSupport() {
        if(carInfo == null){
            carInfo = new Carinfo();
        }
        
        carInfo.setEngine(getEngine);
        carInfo.setYear(getYear());
        return this;
    }
}

以下是我的CarInfo class,它充当围绕MyCar class 构建additional标签的助手:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder = {"engine","year"})
public class Carinfo{
    private String engine;
    private String year;
    //Getter, Setters and other consturctiores ommited
}

以下是我的Main class 它使用JAXBCOntext实际构建XML

public class Main{
    public static void main(String[] args){
        JAXBContext context = JAXBContext.newInstance(MyCar.class);
        Marshaller mar = context.createMarshaller();
        mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        mar.marshal((MyCar).xmlSupport(), System.out);
        System.out.println("-----------------");
    }
}

现在回到我的主要问题:正如我们从MyCar class 中看到的那样,我有XMLSupport方法,它实际上是填充CarInfo对象,然后使用该方法创建XML 有没有办法可以将它移到XMLAdapter

我尝试创建XMLAdapter ,但我不确定如何从适配器填充CarInfo对象:

public class MyCar extends Car{
    
    @XmlElement(name="carInfo")
    @XmlJavaTypeAdapter(ExtensionAdapter.class)
    @XmlElement(name = "carInfo")
    private CarInfo carInfo;
}

以下是我尝试过的Adapter class: public class ExtensionAdapter extends XmlAdapter<CarInfo, CarInfo> {

    @Override
    public CarInfo unmarshal(CarInfo valueType) throws Exception {
        System.out.println("UN-MARSHALLING");
        return null;
    }

    @Override
    public CarInfo marshal(CarInfo boundType) throws Exception {
        System.out.println("MARSHALLING");
        System.out.println(boundType);
        //I get boundType as NULL so I am not sure how to convert the xmlSupport Method to Adapter so I can use this adapter with multiple class
        return null;
    }
}

你不需要任何适配器,你只需要一个定义良好的 POJO。

诀窍是使用 getter 和 setter,而不是字段访问,因此我们可以进行委托,然后使用@JsonIgnore@XmlTransient来控制 JSON 与 XML 使用哪些 getter/setter 方法。

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@XmlRootElement(name = "Car")
@XmlType(propOrder = { "brand", "build", "carinfo" })
@JsonPropertyOrder({ "brand", "build", "engine", "year" })
public final class Car {

    @XmlType(propOrder = { "engine", "year" })
    public static final class Info {
        private String engine;
        private String year;

        public String getEngine() {
            return this.engine;
        }
        public void setEngine(String engine) {
            this.engine = engine;
        }

        public String getYear() {
            return this.year;
        }
        public void setYear(String year) {
            this.year = year;
        }

        @Override
        public String toString() {
            return "Info[engine=" + this.engine + ", year=" + this.year + "]";
        }
    }

    private String brand;
    private String build;
    private Info carinfo;

    public Car() {
        // Nothing to do
    }
    public Car(String brand, String build, String engine, String year) {
        this.brand = brand;
        this.build = build;
        this.carinfo = new Info();
        this.carinfo.setEngine(engine);
        this.carinfo.setYear(year);
    }

    public String getBrand() {
        return this.brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getBuild() {
        return this.build;
    }
    public void setBuild(String build) {
        this.build = build;
    }

    @JsonIgnore // For XML, not JSON
    public Info getCarinfo() {
        if (this.carinfo == null)
            this.carinfo = new Info();
        return this.carinfo;
    }
    public void setCarinfo(Info info) {
        this.carinfo = info;
    }

    @XmlTransient // For JSON, not XML
    public String getEngine() {
        return getCarinfo().getEngine();
    }
    public void setEngine(String engine) {
        getCarinfo().setEngine(engine);
    }

    @XmlTransient // For JSON, not XML
    public String getYear() {
        return getCarinfo().getYear();
    }
    public void setYear(String year) {
        getCarinfo().setYear(year);
    }

    @Override
    public String toString() {
        return "Car[brand=" + this.brand + ", build=" + this.build + ", carinfo=" + this.carinfo + "]";
    }
}

测试

Car car = new Car("Ferari", "Italy", "Mercedes", "2021");

// Generate JSON
ObjectMapper jsonMapper = new ObjectMapper();
jsonMapper.enable(SerializationFeature.INDENT_OUTPUT);
String json = jsonMapper.writeValueAsString(car);

// Generate XML
JAXBContext jaxbContext = JAXBContext.newInstance(Car.class);
Marshaller xmlMarshaller = jaxbContext.createMarshaller();
xmlMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
String xml;
try (StringWriter writer = new StringWriter()) {
    xmlMarshaller.marshal(car, writer);
    xml = writer.toString();
}

// Print generated results
System.out.println(car);
System.out.println(json);
System.out.println(xml);

// Parse JSON
Car carFromJson = jsonMapper.readValue(json, Car.class);
System.out.println(carFromJson);

// Parse XML
Unmarshaller xmlUnmarshaller = jaxbContext.createUnmarshaller();
Car carFromXml = xmlUnmarshaller.unmarshal(new StreamSource(new StringReader(xml)), Car.class).getValue();
System.out.println(carFromXml);

输出

Car[brand=Ferari, build=Italy, carinfo=Info[engine=Mercedes, year=2021]]
{
  "brand" : "Ferari",
  "build" : "Italy",
  "engine" : "Mercedes",
  "year" : "2021"
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Car>
    <brand>Ferari</brand>
    <build>Italy</build>
    <carinfo>
        <engine>Mercedes</engine>
        <year>2021</year>
    </carinfo>
</Car>
Car[brand=Ferari, build=Italy, carinfo=Info[engine=Mercedes, year=2021]]
Car[brand=Ferari, build=Italy, carinfo=Info[engine=Mercedes, year=2021]]

如您所见,生成的 JSON 和 XML 正是您想要的,并且 output 的最后两行表明解析也有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM