I. JSON JavaScript Object Notation
- 복잡한 구조를 가질 수 있는 데이터를 한 줄의 문자열로 표현
- 서버와 클라이언트 등 데이터들을 주고받는 주체들 사이에 널리 사용
II. JSON 객체의 정적 메서드
1. stringify - 객체를 문자열로 직렬화 serialize
const person = {
name: '김달순',
age: 23,
languages: ['Korean', 'English', 'French'],
education: {
school: '한국대',
major: ['컴퓨터공학', '전자공학'],
graduated: true,
}
};
const personStr = JSON.stringify(person);
console.log(typeof personStr);
console.log(personStr);
데이터 형태별 직렬화 결과
[
JSON.stringify(1),
JSON.stringify(Infinity), // ⚠️
JSON.stringify(NaN), // ⚠️
JSON.stringify('가나다'),
JSON.stringify(true),
JSON.stringify(null),
JSON.stringify(undefined),
JSON.stringify([1, 2, 3]),
JSON.stringify({x: 1, y: 2}),
JSON.stringify(new Date()), // ⚠️
]
.forEach(i => console.log(i));
// 이후 배울 Symbol - 직렬화되지 않음
console.log( JSON.stringify(Symbol('hello')) ); // ⚠️
// 이후 배울 BigInt - 오류 발생
console.log( JSON.stringify(1n) ); // ⚠️
⭐️ 값이 함수인 프로퍼티는 직렬화되지 않음
const obj = {
x: 1,
y: 2,
z: function () { return this.x + this.y }
}
console.log(obj.z())
const objStr = JSON.stringify(obj);
console.log(objStr);
const func1 = (a, b) => a + b;
function func2 () { console.log('HELLO'); }
const func1Str = JSON.stringify(func1);
const func2Str = JSON.stringify(func2);
console.log(func1Str);
console.log(func2Str);
💡 2번째 인자: replacer 함수
const obj = {
a: 1,
b: '2',
c: 3,
d: true,
e: false
}
// 1. key와 value 매개변수
const objStr1 = JSON.stringify(obj, (key, value) => {
if (key && key < 'a' || key > 'c') {
// 해당 프로퍼티 생략
return undefined;
// ⚠️ 조건에 key && 을 붙이지 않으면 항상 undefined가 반환됨
// key가 공백('')일 때(value는 객체 자체) undefined를 반환하므로...
// key와 value를 로그로 출력해보며 확인해 볼 것
}
if (typeof value === 'number') {
return value * 10;
}
return value;
});
console.log(objStr1);
// 2. 반환한 key의 배열 매개변수
const objStr2 = JSON.stringify(obj, ['b', 'c', 'd']);
console.log(objStr2);
3번째 인자: 인덴트
const obj = {
a: 1,
b: {
c: 2,
d: {
e: 3
}
}
};
[
JSON.stringify(obj, null),
JSON.stringify(obj, null, 1),
JSON.stringify(obj, null, 2),
JSON.stringify(obj, null, '\t')
]
.forEach(i => console.log(i));
객체의 toJSON 프로퍼티
const obj = {
x: 1,
y: 2,
toJSON: function () {
return '훗, 나를 직렬화해보겠다는 건가';
}
}
console.log(
JSON.stringify(obj)
);
2. parse - 역직렬화
[
JSON.parse('1'),
JSON.parse('"가나다"'), // ⚠️ 안쪽에 따옴표 포함해야 함
JSON.parse('true'),
JSON.parse('null'),
JSON.parse('[1, 2, 3]'),
JSON.parse('{"x": 1, "y": 2}') // ⚠️ key도 따옴표로 감싸야 함
]
.forEach(i => console.log(i));
2번째 인자: receiver 함수
const objStr = '{"a":1,"b":"ABC","c":true,"d":[1,2,3]}';
const obj = JSON.parse(objStr, (key, value) => {
if (key === 'c') {
// 해당 프로퍼티 생략
return undefined;
}
if (typeof value === 'number') {
return value * 100;
}
return value;
});
console.log(obj); // ⚠️ 내부까지 적용(배열 확인해 볼 것)
III. 깊은 복사 deep copy
⭐️ JSON을 사용한 깊은 복사
const obj1 = {
a: 1,
b: {
c: 2,
d: {
e: 3,
f: {
g: 4
}
}
}
}
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1);
console.log(obj2);
obj1.a++;
obj1.b.c++;
obj1.b.d.e++;
obj1.b.d.f.g++;
console.log(obj1);
console.log(obj2);
💡 함수, Date, Symbol, BigInt 프로퍼티는 JSON 방식으로는 불가 또는 제한적
const obj1 = {
a: 1,
b: 2,
c: function () { return this.a + this.b },
d: new Date(),
e: Symbol('안녕'),
// g: 1n // ⚠️ 오류 발생
}
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1);
console.log(obj2);
⭐️ structuredClone
- 아직은 일부 브라우저(Web API 형태로) 및 환경에서만 지원
- JSON 방식보다 빠르고 효율적인 깊은 복사
- Date와 BigInt 제대로 복사 - 함수와 Symbol은 여전히 불가
- 👉 MDN 문서 보기
const obj1 = {
a: 1,
b: 2,
// c: function () { return this.a + this.b },
d: new Date(),
// e: Symbol('안녕'),
g: 1n
}
const obj2 = structuredClone(obj1);
console.log(obj1);
console.log(obj2);