使用Jackson XmlMapper

时间:2019-04-09 21:54:05

标签: java xml jackson jaxb xmlmapper

给出以下xml:

<?xml version="1.0" encoding="utf-8"?>
<live_schedules>
    <title>This Schedule</title>
    <date>20190328</date>
    <link>/v2/schedule</link>
    <id>schedule</id>
    <updated>2019-03-28T21:51:41+0</updated>
    <schedule>
        <sport id="1" name="Football" link="/v2/sport/1">
            <league id="100" name="Alliance of American Football" link="/v2/league/100" />
            <league id="101" name="Alliance of American Football" link="/v2/league/101" />
        </sport>
    </schedule>
</live_schedules>

并且还提供以下类:

LiveScheduleDto.java

package com.stackoverflow.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

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

@Data
@AllArgsConstructor
@XmlRootElement(name = "live_schedule")
@XmlAccessorType(XmlAccessType.FIELD)
public class LiveScheduleWrapper {

    @XmlElement(name = "title")
    private String title;

    @XmlElement(name = "date")
    private String date;

    @XmlElement(name = "link")
    private String link;

    @XmlElement(name = "id")
    private String id;

    @XmlElement(name = "updated")
    private String updatedDate;

    @XmlElement(name = "schedule")
    private ScheduleDto schedule;
}

ScheduleDto.java

package com.stackoverflow.dto;

import lombok.AllArgsConstructor;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "schedule")
class ScheduleDto {

    @XmlElement(name = "sport")
    List<SportDto> sports;
}

SportDto.java

package com.stackoverflow.dto;

import lombok.AllArgsConstructor;
import lombok.Data;

import javax.xml.bind.annotation.*;
import java.util.List;

@Data
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "sport")
public class SportDto {

    @XmlAttribute(name = "id")
    Integer id;

    @XmlAttribute(name = "name")
    String name;

    @XmlAttribute(name = "link")
    String link;

    @XmlElementWrapper(name = "league")
    List<LeagueDto> league;
}

LeagueDto.java

package com.stackoverflow.dto;

import lombok.AllArgsConstructor;

import javax.xml.bind.annotation.*;

@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "league")
public class LeagueDto {

    @XmlAttribute(name = "id")
    String id;

    @XmlAttribute(name = "name")
    String name;

    @XmlAttribute(name = "link")
    String link;
}

执行映射的适配器:

package com.stackoverflow.adaptors;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import com.stackoverflow.dto.LiveScheduleWrapper;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;

import java.io.IOException;

public class ScheduleAdaptor {

    private final HttpClient httpClient;
    private final HttpGet httpGet;

    public ScheduleAdaptor(HttpClient httpClient, HttpGet httpGet) {
        this.httpClient = httpClient;
        this.httpGet = httpGet;
    }

    public HttpApiResponse<LiveScheduleWrapper> retrieveSchedule() {
        try {
            HttpResponse response = httpClient.execute(httpGet);
            XmlMapper mapper = new XmlMapper();
            JaxbAnnotationModule module = new JaxbAnnotationModule();
            mapper.registerModule(module);

            LiveScheduleWrapper schedule =
                    mapper.readValue(response.getEntity().getContent(), LiveScheduleWrapper.class);
            return new HttpApiResponse(response.getStatusLine().getStatusCode(), schedule);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

我在通过解析器运行此程序时看到它将SportDto绑定到LeagueDto,因为我已经将<sport>元素定义为List。这不是我所期望的。相反,我希望它将把Sport XmlElement绑定到SportDto对象,然后将League绑定到我在示例中定义的嵌套League对象。

<sport> xml元素列表正确绑定到SportDto并将<league> xml元素列表正确绑定到LeagueDto的最简单方法是什么?

我应该明确说明我使用的是Jackson的{​​{1}}而不是XmlMapper

1 个答案:

答案 0 :(得分:0)

我设法解决了。我的问题是因为我使用的Jackson XmlMapper功能不如JAXBContext库...

我将retrieveSchedule函数替换为以下内容:

public HttpApiResponse<LiveScheduleWrapper> retrieveSchedule() {
    try {
        HttpResponse response = httpClient.execute(httpGet);
        JAXBContext jc = JAXBContext.newInstance(LiveScheduleWrapper.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        LiveScheduleWrapper schedule = (LiveScheduleWrapper) unmarshaller.unmarshal(response.getEntity().getContent());
        return new HttpApiResponse(response.getStatusLine().getStatusCode(), schedule);
    } catch (JAXBException | IOException e) {
        e.printStackTrace();
    }
    return null;
}

这解决了我的问题,因为JAXBContext可以正确识别XmlMapper上的JAXB批注。