JSON 이란?
JSON(Javascript Object Notation)은 Javascript 객체 문법으로 구조화된 데이터 교환 형식이다. 데이터를 쉽게 교환하고 저장하기 위해 사용하는 대표적인 텍스트 기반의 데이터 교환 양식이라고 볼 수 있다. 여러 언어가 데이터를 교환할 때에 JSON이라는 형식을 사용하며, 객체문법 말고도 배열, 문자열도 표현할 수 있다.
JSON 구조
json 데이터는 key : value 형식의 데이터를 중괄호({})로 둘러쌓아 표현한다.
{ key : value }
아래의 데이터 key값은 "name"이고 value값은 "JSON"이다.
{ "name": "JSON" }
JSON 데이터는 쉼표(,)를 구분자로 사용하여 나열한다.
{
"name": "JSON",
"age": 20
}
JSON의 특징
독립적이다
JSON은 여러 언어와 플랫폼에 대해서 독립적이다. 예를 들어 Javascript와 python의 경우에는 버전이 계속 상승한다. 그러나 JSON은 다른 언어들의 버전이 올라감에 상관없이 변하지 않는다. 이러한 영역에서 독립적이라고 한다. 독립적인 JSON을 사용하기 위해서는 각 언어의 네이티브로 바꾸는 과정이 필요하다.
JSON 문법의 특징
key값 중복선언 불가능
// example.json
{
"name": "testItem1",
"name": "testItem2",
"age": 20
}
// example.js
const fs = require("fs");
const path = require("path");
const jsonData = fs.readFileSync(path.join(__dirname, "example.json"));
const json = JSON.parse(jsonData);
console.log(json);
// 결과
{ name: 'testItem2', age: 20 }
example.json 파일에 name이라는 key값이 중복되어 있다. 출력된 결과물을 보면 나중에 선언한 키에 대응한 값이 덮어 쓰이는 걸 확인할 수 있다.
JSON Array(배열)
여러 개의 JSON Object들을 대괄호([])로 둘러싸서 JSON Array로 만들 수 있다. Key가 없는 배열 형태로 나타내며 인덱스별로 나누어 저장하고 접근한다. 각 Object들은 쉼표(,)를 구분자로 사용하여 구분한다.
[
{ "name": "JSON1", "age": 20 }, // 0번 index
{ "name": "JSON2", "age": 23 } // 1번 index
]
인덱스를 이용하여 1번 인덱스에 접근하는 방법은 아래와 같다.
const fs = require("fs");
const path = require("path");
const jsonData = fs.readFileSync(path.join(__dirname, "example.json"));
const jsonArray = JSON.parse(jsonData);
console.log(jsonArray[1]); // 1번 인덱스 접근
{ name: 'JSON2', age: 23 } // 결과
재귀적 구현
JSON은 value에 Object를 재귀적으로 할당할 수 있다. 접근하는 방법은 key값을 이용하여 접근한다.
{
"name": "JSON",
"age": 75,
"child": {
"name": "JSON junior",
"age": 40,
"child": {
"name": "JSON junior2",
"age": 17
}
}
}
재귀적인 Object에 접근하는 방법은 아래와 같다.
const fs = require("fs");
const path = require("path");
const jsonData = fs.readFileSync(path.join(__dirname, "example.json"));
const json = JSON.parse(jsonData);
console.log(json.child); // 첫 번째 child 접근
{
name: 'JSON junior',
age: 40,
child: { name: 'JSON junior2', age: 17 }
} // 결과
console.log(json.child.child); // 두 번째 child 접근
{ name: 'JSON junior2', age: 17 } // 결과
JSON 데이터 타입
JSON은 데이터의 값으로 사용할 수 있는 데이터 타입을 제공한다. javascript object와 유사하지만 undefined, 메서드 등은 포함하지 않는다.
문자열(String)
큰따옴표("")로 둘러싸인 문자열을 사용할 수 있다.
// JSON String
{ "name" : "JSON" }
숫자(Number)
정수 또는 부동 소수점 숫자를 사용할 수 있다.
// JSON Number type
{ "age": 30, "weight": 73.52 }
불리언(Boolean)
true 또는 false 값을 사용할 수 있다.
// JSON Boolean type
{ "success": true }
배열(Array)
배열은 대괄호([])로 둘러쌓아 표현한다. 또한 쉼표(,)를 사용하여 여러 개의 데이터를 포함할 수 있다.
// JSON Array type
{ "names": ["철수", "영희", "감자"]}
객체(Object)
// JSON Object type
{ "person": { "name": "철수", "age": 30, "weight": 75 } }
null
데이터가 존재하지 않음을 나타내는 값이다. 데이터가 존재하지 않는 것을 명시적으로 나타낼 때 사용한다.
// JSON null
{ "name": null }
JSON 직렬화, 역직렬화
직렬화란 외부의 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터를 변환하는 기술이며 역직렬화는 그 반대를 의미한다.
예를 들어 javascript로 만들어진 서비스와 python으로 만들어진 서비스가 JSON을 이용해 데이터를 교환한다고 가정해 보자. javascript 서비스가 python 서비스에 데이터를 보내려고 한다. 이때 JSObject를 python에서는 사용할 수 없기 때문에 사용할 수 있도록 JSON으로 변환하는 과정이 필요하다. 이 과정을 직렬화라고 한다. python 서비스는 JSON을 바로 사용할 수 없기에 dictionary 타입으로 변환하는 과정이 필요하다. 이 과정을 역직렬화라고 한다.
간단히 말하면 외부의 시스템도 사용할 수 있게 하는 것이 직렬화이며, 외부 시스템으로부터 전달받은 데이터를 사용할 수 있게 만드는 것이 역직렬화라고 볼 수 있다.
const fs = require("fs");
const path = require("path");
const jsonData = fs.readFileSync(path.join(__dirname, "example.json"));
const serialization = JSON.parse(jsonData); // JSON 직렬화
console.log(serialization); // { name: 'JSON', age: 75 }
const deSerialization = JSON.stringify(serialization); // JSON 역직렬화
console.log(deSerialization); // {"name":"JSON","age":75}
같은 것처럼 보이나 조금 다른 것을 확인할 수 있다. 직렬화된 상태는 object이고 역직렬화된 상태는 string인걸 확인할 수 있다. 타입확인을 통해서 좀 더 자세히 알아보자.
const fs = require("fs");
const path = require("path");
const jsonData = fs.readFileSync(path.join(__dirname, "example.json"));
const serialization = JSON.parse(jsonData);
console.log(typeof serialization); // object
const deSerialization = JSON.stringify(serialization);
console.log(typeof deSerialization); // string
JSON의 활용
JSON은 프로그래밍 언어와 프레임워크 등에 독립적이므로, 서로 다른 시스템간에 데이터를 교환하기에 좋다. 주로 API의 반환형태, 시스템을 구성하는 설정파일에 활용된다.