교재를 보면서 공부하다가 API에서 받아온 JSON형식의 데이터를 처리하는 과정에서 의문이 생겼다.
어떤 데이터는 JSONObject로 받고, 또 그렇게 받은 데이터를 JSONArray의 형식으로 무언가를 또 얻어내는 과정이 존재했기 때문이다.
전체를 JSONArray로 받아버리면 안되는가에 대한 궁금증이 들면서,
본질적으로는 두 객체의 차이가 무엇인지를 알아야 이 문제를 해결할 수 있겠다는 판단에 자료 조사를 해보았다.
JSON은 "key-value"
가 쌍으로 이루어진 데이터들의 집합이다.
key와 value 사이를 :
을 이용하여 구분하는 형식을 취한다.
이런 형태의 이점은,
사용자가 value값을 기억 할 필요가 없이 여러 데이터들의 공통된 key값만 알고 있으면 데이터를 손쉽게 추출해 낼 수 있다는 점이다.
이와 관련해서는 뒤에 예를 들어보겠다.
우선 아래의 예를 보자.
"one" : "Suwon"
위와 같은 형태에서는 "one"
이 key
가 되는 것이며, 그에 해당하는 "Suwon"
이 value
가 되어 데이터가 저장되는 것이다.
여기에서, 각 데이터는 String
의 형태로 저장되어 있음을 확인할 수 있다.
하지만 꼭 문자열이 key-value값의 데이터 형식이 될 필요는 없다는 것이 핵심이다.
"name" : "동현"
"age" : 26
"etc" : ["apple", 19, "수원"]
위와 같은 형태로 문자열 뿐 아니라 숫자, 배열
등의 형태로도 작성이 가능하다는 것이다.
특히, 배열은 '[ ]'
의 괄호안에 그 값들을 담으며, comma(,)
로 값을 분리하는 것 역시 파악 가능하다.
같은 주제의 여러 데이터들이 존재하면 공통된 데이터들을 하나로 묶는 것이 가능해진다.
상황을 예로 드는 것이 이해에 좋기 때문에 복잡하지 않은 상황을 제시한다.
도서관에서 빌린 책의 데이터를 정리해보려고 한다.
책은 총 3권이 존재하며, 각 책의 정보는 다음과 같다.
책1. 제목 : 이기적 유전자, 저자 : 리처드 도킨스, 발행일 : 1976
책2. 제목 : 파피용, 저자 : 베르나르 베르베르, 발행일 : 2006
책3. 제목 : 7년의 밤, 저자 : 정유정, 발행일 : 2011
공통된 특성들이 보인다. 모두 책의 종류이며, 제목, 저자, 발행일에 대한 정보가 나열되어 있다.
우선, 책 1을 앞서 언급한 JSON형식으로 정리해본다.
{
"제목" : "이기적 유전자",
"저자" : "리처드 도킨스",
"발행일" : 1976
}
여기서 두가지 설명이 더 가능해진다.
key-value
값은 comma(,)
로 연결한다.'{ }'
를 사용하여 처리한다. 그리고 위의 예처럼 한 개 이상의 key-value들이 중괄호로 묶여진 구조를 객체(Object)
라고 부른다.
또한 여기서 매우 중요한 사실은!!
이러한 객체 역시 '문자열, 숫자, 배열'과 마찬가지로 value값에 속할 수 있다
는 것이다.
이제, 도서관에서 빌렸던 책의 데이터를 다시금 정리해보겠다.
"book1" : {
"제목" : "이기적 유전자",
"저자" : "리처드 도킨스",
"발행일" : 1976
},
"book2" : {
"제목" : "파피용",
"저자" : "베르나르 베르베르",
"발행일" : 2006
},
"book3" : {
"제목" : "7년의 밤",
"저자" : "정유정",
"발행일" : 2011
}
얼추 정리가 된 것 처럼 보인다.
"book1", "book2", "book3" 각각의 key에 대해 Object가 value로 들어가 있는 상태이다.
하지만, 이 모두가 책이라는 공통적인 특성이 존재하는데 그 부분은 묶이지 않은 것 같다.
앞서, 배열을 value값으로 지정했던 원리를 이용하여 다른 형태로 정리해보겠다.
"book" : [{
"제목" : "이기적 유전자",
"저자" : "리처드 도킨스",
"발행일" : 1976
}, {
"제목" : "파피용",
"저자" : "베르나르 베르베르",
"발행일" : 2006
}, {
"제목" : "7년의 밤",
"저자" : "정유정",
"발행일" : 2011
}]
위와 같은 구조로 정리가 가능하다. book이라는 key, 배열안에 여러 object를 넣은 형태를 value로 가지는 꼴이다.
앞서, 여러 데이터들의 공통된 key를 알고있으면 쉽게 데이터를 얻어낼 수 있다고 했는데,
"제목"이라는 key를 조사하면 "이기적 유전자", "파피용", "7년의 밤"의 세 개의 책 모두의 제목 정보를 알 수 있으니 설명이 되었다고 생각한다.
사실 이것에 대한 이야기를 하기 위해서 전반적인 JSON 이야기를 했던건데..
역시 처음 글을 쓰다보니 두서없이 이야기를 다 해버린듯한 느낌이다.
어쨌거나 정리를 해보면!
[ ]
의 대괄호를 이용하여 값들을 담으며, comma(,)
로 그 값을 구분한다.key-value
쌍을 { }
의 중괄호를 이용하여 담고있는 객체 구조이다. colon(:)
으로 한다.comma(,)
로 한다. 여기서부터는 개인적으로 나중에 볼려고 작성하는 글이 된다.
JSONObject와 JSONArray의 구조와 쓰임에 대해 정확히 몰랐기 때문에 코드 자체에 대한 이해가 안됐었다.
간단하게 검색을 통해 문제를 해결했고, 확실하게 JSON에 대해 더 알게 된 계기가 된 것 같다.
// 1번 문제
fun readData(startIndex: Int, lastIndex: Int): JSONObject {
val url = ${API URL}
val connection = url.openConnection()
val data = connection.getInputStream().readBytes().toString(charset("UTF-8"))
return JSONObject(data)
}
val jsonObject = readData(startIndex, lastIndex)
// 2번 문제
val totalCount = jsonObject.getJSONObject("SearchPublicToiletPOIService").getInt("list_total_count")
// 3번 문제
val rows = jsonObject.getJSONObject("SearchPublicToiletPOIService").getJSONArray("row")
이러한 코드들의 이해가 와닿지 않았는데, 이제는 설명이 가능할 것 같다.
{
"SearchPublicToiletPOIService": {
"list_total_count": 4938,
"RESULT": {
"CODE": "INFO-000",
"MESSAGE": "정상 처리되었습니다"
},
"row": [{
"POI_ID": "102423",
"FNAME": "우성스포츠센터",
"ANAME": "민간개방화장실",
"CNAME": "",
"CENTER_X1": 192026.077328,
"CENTER_Y1": 443662.903901,
"X_WGS84": 126.90983237468618,
"Y_WGS84": 37.49238614627172,
"INSERTDATE": "20100712",
"UPDATEDATE": "20100712"
}, {
"POI_ID": "102424",
"FNAME": "프레곤빌딩",
"ANAME": "민간개방화장실",
"CNAME": "",
"CENTER_X1": 191560.448911,
"CENTER_Y1": 442968.699196,
"X_WGS84": 126.90457509912622,
"Y_WGS84": 37.48612718078578,
"INSERTDATE": "20100712",
"UPDATEDATE": "20100712"
}, {
"POI_ID": "102425",
"FNAME": "하림빌딩",
"ANAME": "민간개방화장실",
"CNAME": "",
"CENTER_X1": 201472.042745,
"CENTER_Y1": 443869.796509,
"X_WGS84": 127.01664600669827,
"Y_WGS84": 37.49428349959237,
"INSERTDATE": "20100712",
"UPDATEDATE": "20100712"
}]
}
}
이러한 데이터들의 구조를 잡기가 너무 힘들었는데, 이제는 코드 이해가 된다.
1번은 전체적으로 API의 주소를 연결하여 텍스트를 String으로 받아오고 다시 JSONObject로 받아오는 과정이다.
2번은 SearchPublicToiletPOIService를 key로 했을 때 value값으로 들어있는 Object를 가져오는 것이다.
그 후, Object안의 list_total_count의 key에 대한 value값 4938을 totalCount라는 변수값으로 받는 것이다.
3번도 마찬가지로 SearchPublicToiletPOIService에 해당하는 Object값을 가져온 뒤, row를 key로 하는 value값을 가져오는 것이다.
여기서, value값이 거대한 배열이 되는것인데 array안에는 또 여러개의 object들이 들어있음을 확인할 수 있다.
사실 처음 봤던 raw 형태의 API는 매우 구조화 시키기 힘든.. 꼴이었는데 (아래 글처럼 되어있었다.)
{"SearchPublicToiletPOIService":{"list_total_count":4938,"RESULT":{"CODE":"INFO-000","MESSAGE":"정상 처리되었습니다"},"row":[{"POI_ID":"102423","FNAME":"우성스포츠센터","ANAME":"민간개방화장실","CNAME":"","CENTER_X1":192026.077328,"CENTER_Y1":443662.903901,"X_WGS84":126.90983237468618,"Y_WGS84":37.49238614627172,"INSERTDATE":"20100712","UPDATEDATE":"20100712"},{"POI_ID":"102424","FNAME":"프레곤빌딩","ANAME":"민간개방화장실","CNAME":"","CENTER_X1":191560.448911,"CENTER_Y1":442968.699196,"X_WGS84":126.90457509912622,"Y_WGS84":37.48612718078578,"INSERTDATE":"20100712","UPDATEDATE":"20100712"},{"POI_ID":"102425","FNAME":"하림빌딩","ANAME":"민간개방화장......
이런 배열을 가독성 좋게 바꾸어주는 사이트가 존재했기 때문에 분석이 쉽게 됐다고 생각한다.
https://jsonlint.com/
링크로 걸어두었으니 앞으로도 잘 써먹어야겠다!
역시나 생각했던 것 만큼 글쓰는건 힘들다...
말투 때문에 글이 조금 건방져 보이지는 않을까 걱정이 되는데,
절대 자만심에 기반한 글이 아니라는 것을 알아주셨으면..ㅎㅎ!
잘못된 내용 알려주시거나 피드백 해주시면 반영 하겠습니다.
좋은 글 감사합니다. 많은 도움이 되었습니다.