반응형
배경
네트워크를 통해 객체를 어딘가에 보내거나 로깅 목적으로 객체를 출력해야 한다면
객체를 문자열로 전환해야한다. 이때 전환된 문자열엔 원하는 정보가 있는 객체 프로퍼티 모두가 포함되어야 한다.
let user = {
name: "John",
age: 30,
toString() {
return `{name: "${this.name}", age: ${this.age}}`;
}
};
alert(user); // {name: "John", age: 30}
- 객체를 문자열로 전환하는 메소드 구현
- 그런데 개발 과정에서 프로퍼티가 추가되거나, 삭제, 수정될 수 있는데 이렇게 되면 위에서 구현한 toString을
매번 수정해야하고, 반복문을 돌린다고해도 중첩 객체등으로 인해 객체가 복잡한 경우 이를 문자열로
변경하는건 까다로운 작업이다. 다행히 자바스크립트엔 이런 문제를 해결해주는 방법이 있다.
JSON
JSON (JavaScript Object Notation)은 값이나 객체를 나타내주는 범용 포맷이다.
JSON은 본래 자바스크립트에서 사용할 목적으로 만들어진 포맷인데 라이브러리를 사용하면 자바스크립트가 아닌
언어에서도 충분히 다룰 수 있어서, 데이터 교환 목적으로 사용하는 경우가 많다.
JSON 메소드
JSON.stringify – //객체를 JSON으로 바꿔줍니다.
JSON.parse – //JSON을 객체로 바꿔줍니다.
let student = {
name: 'John',
age: 30,
isAdmin: false,
courses: ['html', 'css', 'js'],
wife: null
};
let json = JSON.stringify(student);
alert(typeof json); // 문자열이네요!
alert(json);
/* JSON으로 인코딩된 객체:
{
"name": "John",
"age": 30,
"isAdmin": false,
"courses": ["html", "css", "js"],
"wife": null
}
*/
- 이렇게 변경된 문자열은 JSON으로 인코딩된, 직렬화 처리된, 문자열로 변환된, 객체라고 부른다.
- 객체는 이렇게 문자열로 변환된 후에야 비로소 네트워크를 통해 전송하거나 저장소에 저장할 수 있다.
JSON으로 인코딩된 객체와 일반 객체와 차이
문자열은 큰따옴표로 감싸야합니다. JSON에선 작은따옴표나 백틱사용불가
객체 프로퍼티 이름은 큰따옴표로 감싸야한다.
JSON.stringify는 원시값에도 적용 가능
// 숫자를 JSON으로 인코딩하면 숫자입니다.
alert( JSON.stringify(1) ) // 1
// 문자열을 JSON으로 인코딩하면 문자열입니다(다만, 큰따옴표가 추가됩니다).
alert( JSON.stringify('test') ) // "test"
alert( JSON.stringify(true) ); // true
alert( JSON.stringify([1, 2, 3]) ); // [1,2,3]
- 객체 { ... }
- 배열 [ ... ]
- 원시형:
- 문자형
- 숫자형
- 불린형 값 true와 false
- null
자바스크립트 특유 객체 프로퍼티는 처리불가
JSON은 데이터 교환을 목적으로 만들어진 언어에 종속되지 않는 포맷입니다.
따라서 자바스크립트 특유의 객체 프로퍼티는 JSON.stringify()가 처리할 수 없습니다.
let user = {
sayHi() { // 무시
alert("Hello");
},
[Symbol("id")]: 123, // 무시
something: undefined // 무시
};
alert( JSON.stringify(user) ); // {} (빈 객체가 출력됨)
- 함수 프로퍼티 (메서드)
- 심볼형 프로퍼티 (키가 심볼인 프로퍼티)
- 값이 undefined인 프로퍼티
중첩 객체 처리가능
let meetup = {
title: "Conference",
room: {
number: 23,
participants: ["john", "ann"]
}
};
alert( JSON.stringify(meetup) );
/* 객체 전체가 문자열로 변환되었습니다.
{
"title":"Conference",
"room":{"number":23,"participants":["john","ann"]},
}
*/
- JSON.stringify의 장점 중 하나는 중첩 객체도 알아서 문자열로 바꿔준다는 점입니다.
순환 참조는 불가능
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: ["john", "ann"]
};
meetup.place = room; // meetup은 room을 참조합니다.
room.occupiedBy = meetup; // room은 meetup을 참조합니다.
JSON.stringify(meetup); // Error: Converting circular structure to JSON
replacer로 원하는 프로퍼티만 직렬화하기
let json = JSON.stringify(value[, replacer, space])
- JSON.stringify의 전체 문법은 아래와 같습니다.
- value - 인코딩 하려는 값
- replacer - JSON으로 인코딩 하길 원하는 프로퍼티가 담긴 배열, 또는 매핑 함수 function(key, value)
- space - 서식 변경 목적으로 사용할 공백 문자 수
- 순환 참조를 다뤄야 하는 경우같이 전환 프로세스를 정교하게 조정하려면 두 번째 인수를 사용해야한다.
let room = {
number: 23
};
let meetup = {
title: "Conference",
participants: [{name: "John"}, {name: "Alice"}],
place: room // meetup references room
};
room.occupiedBy = meetup; // room references meetup
alert( JSON.stringify(meetup, ['title', 'participants', 'place', 'name', 'number']) );
/*
{
"title":"Conference",
"participants":[{"name":"John"},{"name":"Alice"}],
"place":{"number":23}
}
*/
space로 가독성 높이기
space는 가독성을 높이기 위한 용도로 만들여져서 단순 전달 목적이라면 space없이 직렬화하는 편입니다.
let user = {
name: "John",
age: 25,
roles: {
isAdmin: false,
isEditor: true
}
};
alert(JSON.stringify(user, null, 2));
/* 공백 문자 두 개를 사용하여 들여쓰기함:
{
"name": "John",
"age": 25,
"roles": {
"isAdmin": false,
"isEditor": true
}
}
*/
/* JSON.stringify(user, null, 4)라면 아래와 같이 좀 더 들여써집니다.
{
"name": "John",
"age": 25,
"roles": {
"isAdmin": false,
"isEditor": true
}
}
*/
JSON.parse
JSON으로 인코딩된 객체를 다시 객체로 디코딩할 수 있다.
let value = JSON.parse(str, [reviver]);
- str - JSON 형식의 문자열
- reviver - 모든 (key, value) 쌍을 대상으로 호출되는 function(key, value) 형태의 함수로 값을 변경시킬 수 있다.
// 문자열로 변환된 배열
let numbers = "[0, 1, 2, 3]";
numbers = JSON.parse(numbers);
alert( numbers[1] ); // 1
let userData = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,2,3] }';
let user = JSON.parse(userData);
alert( user.friends[1] ); // 1
- 중첩 객체도 사용가능하다.
흔히 하는 실수 참고
let json = `{
name: "John", // 실수 1: 프로퍼티 이름을 큰따옴표로 감싸지 않았습니다.
"surname": 'Smith', // 실수 2: 프로퍼티 값은 큰따옴표로 감싸야 하는데, 작은따옴표로 감쌌습니다.
'isAdmin': false // 실수 3: 프로퍼티 키는 큰따옴표로 감싸야 하는데, 작은따옴표로 감쌌습니다.
"birthday": new Date(2000, 2, 3), // 실수 4: "new"를 사용할 수 없습니다. 순수한 값(bare value)만 사용할 수 있습니다.
"friends": [0,1,2,3] // 이 프로퍼티는 괜찮습니다.
}`;
- [참고] JSON은 주석을 지원하지 않는다는 점! 주석을 추가하면 유효하지 않은 형식이 된다.
reviver 사용하기
문자열을 Date 객체로 전환하기
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let meetup = JSON.parse(str, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
alert( meetup.date.getDate() ); // 이제 제대로 동작하네요!
- 이 방식은 중첩 객체에도 적용할 수 있다.
반응형