-
Section 8. 자바스크립트 Object 깊게 다루기 (JSON)자바스크립트 2023. 4. 6. 11:56
I. JSON JavaScript Object Notation
이런 형태로 작성된 문서를 XML이라고 한다. XML은 간단히 말해서 복잡할 수 있는 정보를 서버와 클라이언트에서 주고 받기 적합한 형태로 표현한 것이라고 한다. tag를 사용하여 정보와 구조가 명확하게 드러나는 특징이 있다.
하지만 가독성이 조금 떨어질 수 있는데 여기서 강점을 가질 수 있는 것이 바로 JSON이다.
JSON은 보다 간결한 형태로 구조화된 정보를 표기한다.
JSON은 정리를 하자면 다음과 같다
- 복잡한 구조를 가질 수 있는 데이터를 한 줄의 문자열로 표현한 것.
- 서버와 클라이언트 등 데이터들을 주고받는 주체들 사이에 널리 사용된다.
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); //string console.log(personStr); //{"name":"김달순","age":23,"languages":["Korean","English","French"], "education":{"school":"한국대","major":["컴퓨터공학","전자공학"],"graduated":true}}
객체 personStr이 문자열로 직렬화가 되어서 출력이 되었다.
데이터 형태별 직렬화 결과는 다음과 같다
[ JSON.stringify(1), //1 JSON.stringify(Infinity), //null JSON.stringify(NaN), //null JSON.stringify('가나다'), //"가나다" JSON.stringify(true), //true JSON.stringify(null), //null JSON.stringify(undefined), //undefined JSON.stringify([1, 2, 3]), //[1,2,3] JSON.stringify({x: 1, y: 2}), //{"x":1,"y":2} JSON.stringify(new Date()), //"2023-04-06T02:02:13.397Z" ] .forEach(i => console.log(i));
Infinity와 NaN은 직렬화 처리가 되지 않아 null이 된 것을 알 수 있고 Date는 부분적으로만 직렬화가 된 것을 알 수 있다.
값이 함수인 프로퍼티는 직렬화되지 않는다
const obj = { x: 1, y: 2, z: function () { return this.x + this.y } } console.log(obj.z()) //3 const objStr = JSON.stringify(obj); console.log(objStr); //{"x":1,"y":2}
z는 직렬화가 되지 않는다.
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); //{"a":10,"b":"2","c":30}
key가 a보다 작거나 c보다 크면 undefined를 반환하라고 해서 d와 e는 직렬화가 되지 않는 것을 확인할 수 있다. 즉, undefined를 반환하라는 것은 생략하라는 의미이다.
그리고 값이 숫자인 경우에는 10을 곱해서 반환하라고 해서 값에 10이 곱해져서 직렬화가 된 것을 볼 수 있다.
이렇게 어떤 객체를 직렬화 할때 조건을 넣어 줄 수 있다.
아니면 어떤 프로퍼티만 직렬화가 되게끔 명시를 하는 방법도 있다.
// 2. 반환한 key의 배열 매개변수 const objStr2 = JSON.stringify(obj, ['b', 'c', 'd']); console.log(objStr2); //{"b":"2","c":3,"d":true}
3번째 인자 : 인덴트
만약에 직렬화된 문자열이 조금 알아보기 쉽게 되었으면 좋겠다~ 라고 한다면 3번째 인자를 통해 인덴트 한다.
const obj = { a: 1, b: { c: 2, d: { e: 3 } } }; [ JSON.stringify(obj, null), //{"a":1,"b":{"c":2,"d":{"e":3}}} JSON.stringify(obj, null, 1), JSON.stringify(obj, null, 2), JSON.stringify(obj, null, '\t') ] .forEach(i => console.log(i));
이처럼 3번째 인자에 어떤 조건을 주느냐에 따라서 직렬화의 모양을 바꿀 수 있다.
객체의 toJSON 프로퍼티
const obj = { x: 1, y: 2, toJSON: function () { return '철권8 언제 나와?'; } } console.log( JSON.stringify(obj) ); //"철권8 언제 나와?"
toJSON은 어떤 객체가 직렬화가 될때 이런 값을 리턴해라~ 라고 정의 해주는 것이다.
어떤 객체에다가 toJSON 프로퍼티를 함수로 넣어주게 되면 직렬화가 될때 그 함수가 실행 된다.
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)); //1 //가나다 //true //null //[1, 2, 3] //{x: 1, y: 2}
직렬화와 반대로 작동하는 것을 볼 수 있다.
자바스크립트 코드가 문자열로 들어가는 것이기 때문에 코드가 문자열일 경우는 따옴표로 감싸주어야 한다.
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); // ⚠️ 내부까지 적용(배열 확인해 볼 것) //a: 100, b: 'ABC', d: Array(3)}
내부까지 적용이 된 것을 볼 수 있다.
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);
obj2에 obj1을 직렬화 한것에 역직렬화를 한것을 할당했고 obj1의 프로퍼티를 1씩 증가시킨다음 둘다 출력을 해보면 다음과 같다.
obj2는 obj1의 영향을 받지 않은 것을 볼 수 있다.
이유는 obj2는 obj1과 같은 값을 참조하는 게 아니라 문자열을 받아서 그걸 해석해서 값이 나온(역직렬화) 완전 새로운 것을 obj2에 할당 했기 때문이다. 완전히 다른 객체가 할당이 된 것.
함수, Date, Symbol, BigInt 프로퍼티는 JSON 방식으로는 불가 또는 제한적이라는 사실을 알고 넘어가자.
structuredClone이라는 것이 있다. 특징은 다음과 같다
- 아직은 일부 브라우저 및 환경에서만 지원한다.
- JSON 방식보다 빠르고 효율적인 깊은 복사가 된다.
- Date와 BigInt를 제대로 복사한다.
일단은 이런게 있다는 사실만 알고 넘어가자.
'자바스크립트' 카테고리의 다른 글
Section 9. 자바스크립트 BigInt (0) 2023.04.06 Section 9. 자바스크립트 2, 8, 16진법과 비트 연산자 (0) 2023.04.06 Section 8. 자바스크립트 Object 깊게 다루기 (프로퍼티 어트리뷰트) (0) 2023.04.06 Section 8. 자바스크립트 Object 깊게 다루기 (0) 2023.04.05 Section 7. 자바스크립트 배열의 스프레드와 디스트럭쳐링 (0) 2023.04.05