Skip to content

Commit

Permalink
✨ 법정동코드 조회 API 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
allbegray committed Mar 27, 2023
1 parent 7203327 commit 6f36993
Show file tree
Hide file tree
Showing 26 changed files with 227 additions and 7 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
# spring-boot-starter-datakr
spring boot starter datakr. data.go.kr 공공데이터 스프링부트용 라이브러리

## Supported APIs
[국립중앙의료원_국립중앙의료원_전국 병·의원 찾기 서비스 - 병/의원 FullData 내려받기](https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15000736)

[한국천문연구원_특일 정보 - 공휴일 정보 조회](https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15012690)

[행정안전부_행정표준코드_법정동코드 - 법정동코드 조회](https://www.data.go.kr/data/15077871/openapi.do?recommendDataYn=Y)
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ plugins {
}

group = 'herbaccara'
version = '0.0.3'
version = '0.0.4'
sourceCompatibility = '1.8'

publishing {
Expand Down Expand Up @@ -38,6 +38,8 @@ dependencies {
implementation 'org.jetbrains.kotlin:kotlin-reflect'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'

implementation 'org.springframework:spring-context:5.3.20'
implementation 'org.springframework:spring-web:5.3.20'

Expand Down
67 changes: 61 additions & 6 deletions src/main/kotlin/herbaccara/datakr/DataKrService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper
import herbaccara.boot.autoconfigure.datakr.DataKrProperties
import herbaccara.datakr.model.HolidayResult
import herbaccara.datakr.model.HopitalResult
import herbaccara.datakr.model.StanReginCd
import kotlinx.coroutines.*
import org.springframework.util.LinkedMultiValueMap
import org.springframework.web.client.RestTemplate
import org.springframework.web.client.getForObject
Expand All @@ -16,13 +18,15 @@ class DataKrService(
private val xmlMapper: XmlMapper,
private val properties: DataKrProperties
) {
private fun <T> getForObject(uri: String, params: Map<String, Any>, clazz: Class<T>): T {
private fun <T> getForObject(uri: String, params: Map<String, Any?>, clazz: Class<T>): T {
val endpoint = UriComponentsBuilder
.fromHttpUrl("${properties.rootUri}$uri")
.queryParams(
LinkedMultiValueMap<String, String>().apply {
for ((k, v) in params) {
add(k, v.toString())
if (v != null) {
add(k, v.toString())
}
}
}
)
Expand Down Expand Up @@ -61,8 +65,12 @@ class DataKrService(
totalPage++
}

(1..totalPage)
.forEach { pageNo: Int -> block(getHsptlMdcncFullDown(pageNo, numOfRows)) }
runBlocking {
(1..totalPage)
.forEach { pageNo: Int ->
launch(Dispatchers.IO) { block(getHsptlMdcncFullDown(pageNo, numOfRows)) }
}
}
}

fun getHsptlMdcncFullDown(numOfRows: Int): List<HopitalResult> {
Expand All @@ -89,7 +97,54 @@ class DataKrService(
}

fun getRestDeInfo(solYear: Int): List<HolidayResult> {
return (1..12)
.map { getRestDeInfo(solYear, it) }
return runBlocking {
(1..12)
.map {
async(Dispatchers.IO) { getRestDeInfo(solYear, it) }
}
.awaitAll()
}
}

/***
* 행정안전부_행정표준코드_법정동코드 - 법정동코드 조회
* https://www.data.go.kr/data/15077871/openapi.do?recommendDataYn=Y
*/
@JvmOverloads
fun getStanReginCdList(pageNo: Int, numOfRows: Int, locataddNm: String? = null): StanReginCd {
val uri = "/1741000/StanReginCd/getStanReginCdList"

return getForObject(
uri,
mapOf(
"pageNo" to pageNo,
"numOfRows" to numOfRows,
"type" to "xml",
"locatadd_nm" to locataddNm
),
StanReginCd::class.java
)
}

fun getStanReginCdList(numOfRows: Int, block: (StanReginCd) -> Unit) {
val totalCount = getStanReginCdList(1, 1).head.totalCount

var totalPage = totalCount / numOfRows
if (totalCount % numOfRows > 0) {
totalPage++
}

runBlocking {
(1..totalPage)
.forEach { pageNo: Int ->
launch(Dispatchers.IO) { block(getStanReginCdList(pageNo, numOfRows)) }
}
}
}

fun getStanReginCdList(numOfRows: Int): List<StanReginCd> {
val list = mutableListOf<StanReginCd>()
getStanReginCdList(numOfRows, list::add)
return list
}
}
88 changes: 88 additions & 0 deletions src/main/kotlin/herbaccara/datakr/model/StanReginCd.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package herbaccara.datakr.model

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement

@JacksonXmlRootElement(localName = "StanReginCd")
data class StanReginCd(
val head: Head,
@field:JacksonXmlElementWrapper(useWrapping = false) val row: List<Row>
) {
data class Head(
val totalCount: Int,
val numOfRows: Int,
val pageNo: Int,
val type: String,
@field:JsonProperty("RESULT") val result: Result
) {
data class Result(val resultCode: String, val resultMsg: String)
}

data class Row(
/***
* 지역코드
*/
@field:JsonProperty("region_cd") val regionCd: String,

/***
* 시도코드
*/
@field:JsonProperty("sido_cd") val sidoCd: String,

/***
* 시군구코드
*/
@field:JsonProperty("sgg_cd") val sggCd: String,

/***
* 읍면동코드
*/
@field:JsonProperty("umd_cd") val umdCd: String,

/***
* 리코드
*/
@field:JsonProperty("ri_cd") val riCd: String,

/***
* 지역코드_주민
*/
@field:JsonProperty("locatjumin_cd") val locatjuminCd: String,

/***
* 지역코드_지적
*/
@field:JsonProperty("locatjijuk_cd") val locatjijukCd: String,

/***
* 지역주소명
*/
@field:JsonProperty("locatadd_nm") val locataddNm: String,

/***
* 서열
*/
@field:JsonProperty("locat_order") val locatOrder: Int,

/***
* 지역주소명
*/
@field:JsonProperty("locat_rm") val locatRm: String,

/***
* 상위지역코드
*/
@field:JsonProperty("locathigh_cd") val locathighCd: String,

/***
* 최하위지역명
*/
@field:JsonProperty("locallow_nm") val locallowNm: String,

/***
* 생성일
*/
@field:JsonProperty("adpt_de") val adptDe: String
)
}
47 changes: 47 additions & 0 deletions src/test/kotlin/herbaccara/datakr/DataKrServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package herbaccara.datakr

import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import herbaccara.boot.autoconfigure.datakr.DataKrAutoConfiguration
import herbaccara.datakr.model.Hopital
import herbaccara.datakr.model.Result
import herbaccara.datakr.model.StanReginCd
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestPropertySource
import java.io.File

@SpringBootTest(
classes = [
Expand All @@ -21,6 +25,10 @@ class DataKrServiceTest {
@Autowired
lateinit var dataKrService: DataKrService

private val objectMapper = jacksonObjectMapper().apply {
findAndRegisterModules()
}

@Test
fun xmlMapper() {
val xml = DataKrServiceTest::class.java.getResourceAsStream("/test.xml")!!.reader().readText()
Expand Down Expand Up @@ -49,4 +57,43 @@ class DataKrServiceTest {
val hsptlMdcncFullDown = dataKrService.getHsptlMdcncFullDown(1, 1000)
println(hsptlMdcncFullDown)
}

@Test
fun getHsptlMdcncFullDowns() {
val hsptlMdcncFullDowns = dataKrService.getHsptlMdcncFullDown(5_000)
println()
}

@Test
fun getStanReginCdList() {
(1..21).forEach {
try {
val stanReginCdList = dataKrService.getStanReginCdList(it, 1000)
val json = objectMapper.writeValueAsString(stanReginCdList)
val file = File("src/test/resources/StanReginCd/$it.json")
file.writeText(json)
} catch (e: Exception) {
println("error page $it")
}
}
}

@Test
fun getStanReginCdListFull() {
val stanReginCdList = dataKrService.getStanReginCdList(1000)
println()
}

@Test
fun getStanReginCdListFromJson() {
val files = File("src/test/resources/StanReginCd").listFiles() ?: emptyArray()
val rows = files.flatMap {
val stanReginCd = objectMapper.readValue<StanReginCd>(it.readText())
stanReginCd.row
}
val level1 = rows.filter { it.sggCd == "000" }.sortedBy { it.sidoCd } // 특별시, 광역시, 도
val level2 = rows.filter { it.sggCd != "000" && it.umdCd == "000" }
.sortedWith(compareBy({ it.sidoCd }, { it.locatOrder }))
println()
}
}
1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/1.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/10.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/11.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/12.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/13.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/14.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/15.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/16.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/17.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/18.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/19.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/2.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/20.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/21.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/3.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/4.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/5.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/6.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/7.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/8.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/test/resources/StanReginCd/9.json

Large diffs are not rendered by default.

0 comments on commit 6f36993

Please sign in to comment.