본문 바로가기

My Proect/중개폼 프로젝트 - Carblre

2일차 - 공공 API XML to JSON 변환하기

▶ 필요한 데이터 https://opendata.koroad.or.kr/

 

KOROAD OPEN API POTAL

공공 데이터 개방 추진 사업의 일환으로 사고다발지정보(13종), 교통안전정보(3종), 사망사고정보(1종), 교통사고통계(1종) 를 개방합니다.

opendata.koroad.or.kr

 

▶ 교통사고정보 개방 시스템의 사망교통사과정보 API는 JSON 형식이 아니라 XML 형태로 날아옴

 

 

 

제일 먼저 DTO 생성

AccidentProneAreasDTO
package com.carblre.dto;

import lombok.*;
import lombok.Data;

/**
 * 법규위반별 사고다발지역 API
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
 public class AccidentProneAreasDTO {

    private String resultCode; // 결과코드
    private String resultMsg; // 결과메시지
    private Items items;
    private int totalCount; // 총건수
    private int numOfRows; // 검색건수
    private int pageNo; // 페이지 번호

}

▶ 다른 사람들이 보고 어떤 파일인지 알아야하기 때문에 제일 상단에 법규위반별 사고다발지역 API라고 명시

 

 

Item
package com.carblre.dto;

import lombok.*;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class Items {

    private List<Item> item;

    static class Item {

        private SearchYearDTO accYear; // 사고년도
        private String occrrncDt; // 월일시
        private String dghtCd; // 주야구분코드
        private String occrrncDayCd; // 요일코드
        private int dthDnvCnt; // 사망자수
        private int injpsnCnt; // 부상자수
        private int seDnvCnt; // 중상자수
        private int slDnvCnt; // 경상자수
        private int wndDnvCnt; // 부상신고자수
        private String occrrncLcSidoCd; // 위치 시도 코드
        private String occrrncLcSggCd; // 위치 시군구 코드
        private String accTyLclasCd; // 사고유형 대분류 코드
        private String accYyMlsfcCd; // 사고유형 중분류 코드
        private String accTyCd; // 사고유형 코드
        private String asltVtrCd; // 가해자 법규위반 코드
        private String roadFrmLclasCd; // 도로형태 대분류 코드
        private String roadFrmCd; // 도로형태 코드
        private String wrngdoIsrtyVhctyLclasCd; // 가해당사자 차종별 대분류 코드
        private String dmgeIsrtyVhctyLclasCd; // 피해당사자 차종별 대분류 코드
        private String occrrncLcXCrd; // 위치 X 좌표
        private String occrrncLcYCrd; // 위치 Y 좌표
        private String loCrd; // 경도 좌표
        private String laCrd; // 위도 좌표

    }

}

 Items는 또 다른 배열이기 때문에 따로 ItemsDTO를 생성

▶ 변수이름을 보고는 뭐가 뭔지 모르기 때문에 주석으로 표시

 

 

SearchYearDTO
package com.carblre.dto;

import lombok.*;

/**
 * 사고 년도 - accYear
 */

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
public class SearchYearDTO {

    private String year2012;
    private String year2013;
    private String year2014;
    private String year2015;
    private String year2016;
    private String year2017;
    private String year2018;
    private String year2019;
    private String year2020;
    private String year2021;
    private String year2022;
    private String year2023;

}

 

 

 

SiDoDTO
package com.carblre.dto;

import ch.qos.logback.classic.spi.ThrowableProxyUtil;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import org.apache.catalina.startup.ConnectorCreateRule;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
public class SiDoDTO {

    private String 시도명;

    private AccidentProneAreasDTO accidentProneAreasDTO;

    public SiDoDTO(AccidentProneAreasDTO accidentProneAreasDTO) {
        this.accidentProneAreasDTO = accidentProneAreasDTO;
    }

    private String convertToSidoName(String code){
        switch (code){
            case "1100":
                return "서울특별시";
            case "1200":
                return "부산광역시";
            case "2500":
                return "대전광역시";
            case "2200":
                return "대구광역시";
            case "2400":
                return "광주광역시";
            case "2300":
                return "인천광역시";
            case "2600":
                return "울산광역시";
            case "2700":
                return "세종특별자치시";
            case "1300":
                return "경기도";
            case "1400":
                return "강원특별자치도";
            case "1600":
                return "충청남도";
            case "1500":
                return "충청북도";
            case "1800":
                return "전라남도";
            case "1700":
                return "전북특별자치도";
            case "2000":
                return "경상남도";
            case "1900":
                return "경상북도";
            case "2100":
                return "제주특별자치도";
            default:
                return "알수없음";
        }
    }

}

 

 


 

 

XML to JSON 작업

build.gradle 에 의존성 추가
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.10'
    id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
    implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
    implementation 'javax.servlet:jstl:1.2' // 버전을 명시합니다.
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'com.h2database:h2'
    runtimeOnly 'com.mysql:mysql-connector-j'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

    implementation 'org.json:json:20210307'
    implementation group: 'commons-io', name: 'commons-io', version: '2.9.0'
}

tasks.named('test') {
    useJUnitPlatform()
}

implementation 'org.json:json:20210307'
implementation group: 'commons-io', name: 'commons-io', version: '2.9.0'

 

 

 

ProtoApplication
package com.carblre.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.json.JSONObject;
import org.json.XML;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

/**
 * XML to JSON 변환 작업
 */
@SpringBootApplication
public class ProtoApplication {

    public static void xmlToJson(String str){

        try{
            String xml = str;
            JSONObject jObject = XML.toJSONObject(xml);
            ObjectMapper mapper = new ObjectMapper();
            mapper.enable(SerializationFeature.INDENT_OUTPUT);
            Object json = mapper.readValue(jObject.toString(), Object.class);
            String output = mapper.writeValueAsString(json);
            System.out.println(output);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        SpringApplication.run(ProtoApplication.class, args);

        String urlString = "https://opendata.koroad.or.kr/data/rest/accident/death?authKey=C1jDh3auy3SiXY9mcqxx6KjXz1vDcKsv%2BYZDwZlTn6HselD1s5gIHxSoKJOrC5Pc&searchYear=2023&siDo=1100&guGun=1117";

        URL url = new URL(urlString);
        BufferedReader bf = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));

        StringBuilder resultBuilder = new StringBuilder();
        String line;

        while ((line = bf.readLine()) != null) {
            resultBuilder.append(line);
        }

        String result = resultBuilder.toString();
        xmlToJson(result);

    }

}

 

 

 

ERROR

처음에 BufferedReader 로 했는데 한 줄 밖에 못 읽었다. 이후 StringBuilder로 하니 xml -> json으로 잘 변환하는걸 확인

 

검색해보니 

  1. 용도
    • BufferedReader는 데이터를 읽는 데 사용된다.
    • StringBuilder는 문자열을 생성하고 수정하는 데 사용된다.
  2. 성능
    • BufferedReader는 I/O 성능을 개선하는 데 중점을 둔다.
    • StringBuilder는 문자열 조작 성능을 개선하는 데 중점을 둔다.
  3. 사용 시점
    • BufferedReader는 파일 또는 네트워크로부터 데이터를 읽을 때 사용한다.
    • StringBuilder는 문자열을 생성하거나 결합할 때 사용한다 .

이 두 클래스를 조합하여, BufferedReader로 데이터를 읽고 StringBuilder로 읽은 데이터를 누적하여 사용할 수 있다.

 

728x90