Programming/Java

XML to Java Object 변환하기 JAXB API

Jan92 2021. 9. 28. 23:57
반응형

XML to Java Object

 

JAXB api를 사용하여 XML 형식의 데이터를 자바 객체로 변환하는 방법입니다.

 

지금까지 JSON 형식의 데이터만 접해보다가 이번에 공공데이터 포털의 open api를 사용하며 데이터 포멧이 XML인 경우를 처음 접해봤습니다. 데이터를 조회하여 xml 형식으로 뽑아오는 것은 금방 할 수 있었지만, 조회된 XML 데이터를 자바 객체로 변환하는 것은 생소하여 생각보다 시간이 걸렸습니다.

 

해당 포스팅은 JAXB에 대한 구체적인 내용과 설명, 이해에 관한 내용 없이 단순하게 XML 데이터를 Java Object로 변환하는 과정만 담았습니다. 추후 해당 내용에 대해 더 공부하여 구체적인 설명과 함께 다시 포스팅을 작성하도록 하겠습니다.

 

 


 

 

Spring Boot Starter Test

JAXB (Java Architecture for XML Binding)는 자바 클래스를 XML로 표현하는 자바 API입니다. 주 기능은 자바 객체를 XML로 직렬화 하는 것과 XML에서 자바 객체로 역직렬화하는 것입니다.

 

Spring Boot Starter Test는 jakarta.xml.bind를 포함하고 있기 때문에 따로 의존성을 추가할 필요 없이  바로 사용할 수 있습니다.

 

 


 

 

XML Data

open api를 사용하여 분양 정보를 조회하면 다음과 같은 XML 데이터를 얻을 수 있습니다.

이제 해당하는 데이터 형식을 담을 객체를 만들어야 하는데요.

 

* 아래 예시와 같이 그대로 담을 수도 있지만 필요한 부분만 부분적으로 담을 수도 있습니다.

 

 

<response>
    <header>
        <resultCode></resultCode>
        <resultMsg></resultMsg>
    </header>
    <body>
        <items>
            <item></item>
            <item></item>
        </items>
        <numOfRows></numOfRows>
        <pageNo></pageNo>
        <totalCount></totalCount>
    </body>
</response>

만들어야하는 객체의 큰 형태를 보면 다음과 같습니다. 가장 큰 틀로 response가 있고, 아래 header와 body가 있습니다.

header 아래는 resultCode, resultMsg가 있고, body 아래는 items, numOfRows, pageNo, totalCount가 있습니다. 또 items 아래는 list 형식의 item들이 존재합니다.

 

 


 

import lombok.Getter;
import lombok.Setter;

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

@Getter
@Setter
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "response")
public class Response {

    @XmlElement(name = "header")
    private Header header;

    @XmlElement(name = "body")
    private Body body;

    @Getter
    @Setter
    @XmlRootElement(name = "header")
    private static class Header {

        private String resultCode;
        private String resultMsg;
    }

    @Getter
    @Setter
    @XmlRootElement(name = "body")
    private static class Body {

        private Items items;
        private String numOfRows;
        private String pageNo;
        private String totalCount;

        @Getter
        @Setter
        @XmlRootElement(name = "items")
        private static class Items {

            private List<Item> item;

            @Getter
            @Setter
            @XmlRootElement(name = "item")
            public static class Item {

                private String bsnsMbyNm;
                private String houseDtlSecdNm;
                private String houseManageNo;
                private String houseNm;
                private String pblancNo;
                private String przwnerPresnatnDe;
                private String rceptBgnde;
                private String rceptEndde;
                private String rcritPblancDe;
                private String rentSecdNm;
                private String sido;
            }
        }
    }
}

 

위에 xml 데이터 형식에 맞춰 생성된 Response 객체는 다음과 같습니다.

@XmlAccessorType,  @XmlElement,  @XmlRootElement 어노테이션이 사용되었는데, 대략적인 내용은 다음과 같습니다.

 

  • @XmlAccessorType : XML 데이터를 어떤 방법으로 매핑할지를 선언해줄 수 있는 annotation입니다.
  • @XmlRootElement : Class에 사용하는 annotation으로 해당 클래스가 XML의 특정 노드의 루트라는 것을 뜻합니다.
  • @XmlElement : 변수에 사용하는 annotation으로 해당 변수가 XML의 노드임을 뜻합니다.

 

 


 

 

@GetMapping("/xmlToJavaObject")
    public ResponseEntity<?> xmlToJavaObject() throws IOException, JAXBException {

        StringBuilder urlBuilder = new StringBuilder("http://openapi.reb.or.kr/OpenAPI_ToolInstallPackage/service/rest/ApplyhomeInfoSvc/getLttotPblancList"); /*URL*/
        urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "=" + URLEncoder.encode(decodingKey, "UTF-8")); /*공공데이터포털에서 받은 인증키*/
        urlBuilder.append("&" + URLEncoder.encode("startmonth","UTF-8") + "=" + URLEncoder.encode("202101", "UTF-8")); /*월 단위 모집공고일 (검색시작월)*/
        urlBuilder.append("&" + URLEncoder.encode("endmonth","UTF-8") + "=" + URLEncoder.encode("202103", "UTF-8")); /*월 단위 모집공고일 (검색종료월, 최대 12개월)*/
        urlBuilder.append("&" + URLEncoder.encode("houseSecd","UTF-8") + "=" + URLEncoder.encode("01", "UTF-8")); /*주택구분*/
        urlBuilder.append("&" + URLEncoder.encode("sido","UTF-8") + "=" + URLEncoder.encode("부산", "UTF-8")); /*공급지역*/
        urlBuilder.append("&" + URLEncoder.encode("houseName","UTF-8") + "=" + URLEncoder.encode("", "UTF-8")); /*주택명*/
        urlBuilder.append("&" + URLEncoder.encode("rentSecd","UTF-8") + "=" + URLEncoder.encode("0", "UTF-8")); /*분양/임대 구분값*/
        URL url = new URL(urlBuilder.toString());

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/json");

        BufferedReader rd;
        if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        } else {
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        rd.close();
        conn.disconnect();
        
        // String 형식의 xml
        String xml = sb.toString();

        // String 형식의 xml을 Java Object인 Response로 변환
        Map<String, Response> result = new HashMap<>();
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(Response.class); // JAXB Context 생성
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();  // Unmarshaller Object 생성
            Response apiResponse = (Response) unmarshaller.unmarshal(new StringReader(xml)); // unmarshall 메서드 호출
            result.put("response", apiResponse);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
        return response.success(result);
    }

예시를 위한 컨트롤러입니다.

위 부분은 open api 요청이므로 크게 신경 쓰지 않으셔도 되고, 요청에 대한 XML 형식의 응답 데이터를 String화 한 이후부터가 JAXB를 사용하여 XML 데이터를 객체화하는 과정입니다.

 

 

    JAXBContext jaxbContext = JAXBContext.newInstance(Response.class); // JAXB Context 생성
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();  // Unmarshaller Object 생성
    Response apiResponse = (Response) unmarshaller.unmarshal(new StringReader(xml)); // unmarshall 메서드 호출

응답되는 xml 데이터 형식을 보고 원하는 데이터를 받을 객체를 만드는 것이 핵심이 되고, 해당 세 줄을 통해 JAXB의 역직렬화 기능이 실행됩니다.

반응형