JSONObject와 JSONArray의 차이와 전반적인 JSON형식에 대한 이야기

이동현·2020년 7월 9일
9

개요

교재를 보면서 공부하다가 API에서 받아온 JSON형식의 데이터를 처리하는 과정에서 의문이 생겼다.
어떤 데이터는 JSONObject로 받고, 또 그렇게 받은 데이터를 JSONArray의 형식으로 무언가를 또 얻어내는 과정이 존재했기 때문이다.
전체를 JSONArray로 받아버리면 안되는가에 대한 궁금증이 들면서,
본질적으로는 두 객체의 차이가 무엇인지를 알아야 이 문제를 해결할 수 있겠다는 판단에 자료 조사를 해보았다.

JSON형식

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
}

여기서 두가지 설명이 더 가능해진다.

  1. 서로 다른 key-value값은 comma(,)로 연결한다.
  2. 한 객체의 여러 정보를 하나로 묶을 때 '{ }'를 사용하여 처리한다.

그리고 위의 예처럼 한 개 이상의 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년의 밤"의 세 개의 책 모두의 제목 정보를 알 수 있으니 설명이 되었다고 생각한다.

JSONObject와 JSONArray

사실 이것에 대한 이야기를 하기 위해서 전반적인 JSON 이야기를 했던건데..
역시 처음 글을 쓰다보니 두서없이 이야기를 다 해버린듯한 느낌이다.

어쨌거나 정리를 해보면!

  1. JSONArray
    • 배열 구조이다.
    • 배열 안에는 문자열, 숫자, 배열, 객체 등을 담을 수 있다.
    • [ ]의 대괄호를 이용하여 값들을 담으며, comma(,)로 그 값을 구분한다.
    • 후에 index를 이용하여 값을 꺼낼 수 있으므로 그 순서에 대한 고려를 해주어야 한다.
  2. JSONObject
    • 하나 이상의 key-value 쌍을 { }의 중괄호를 이용하여 담고있는 객체 구조이다.
    • key와 value 사이의 구분은 colon(:)으로 한다.
    • key-value 묶음간의 구분은 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/
링크로 걸어두었으니 앞으로도 잘 써먹어야겠다!

글 쓰고나서

역시나 생각했던 것 만큼 글쓰는건 힘들다...
말투 때문에 글이 조금 건방져 보이지는 않을까 걱정이 되는데,
절대 자만심에 기반한 글이 아니라는 것을 알아주셨으면..ㅎㅎ!

잘못된 내용 알려주시거나 피드백 해주시면 반영 하겠습니다.

profile
영차영차

6개의 댓글

comment-user-thumbnail
2020년 11월 29일

좋은 글 감사합니다. 많은 도움이 되었습니다.

1개의 답글
comment-user-thumbnail
2022년 7월 22일

저도 많은 도움이 되었습니다. 좋은 글 감사합니다.

1개의 답글
comment-user-thumbnail
2022년 9월 14일

정리를 차근차근 잘 해주셔서 쉽게 이해할 수 있었습니다 감사합니다!!

1개의 답글