TIL/JS

JSON

yyeon111 2023. 3. 28. 15:17

JSON은 컴퓨터가 이해 할 수 있도록, 포맷된 데이터 형식이다.

JSON은 Javascript Object Notation의 약자로, Javascript 에서 영감을 얻어 만들었기 때문에, 생김이 비슷하다.

 

⚪ JSON.stringify()

Json의 정적 메서드인 stringify를 사용해서, 직렬화를 할 수 있다.

직렬화 한 상태의 타입은 string이다.

❗ Infinity, NaN는 Json을 했을 시, null로 직렬화된다.

new Date()는, JavaScript와 달리, 9시간 시차가 나기 때문에 정확성이 부족하다.

Symbol과 함수는 undefined가 되어, 해당 프로퍼티를 제외하고 stringify된다.

BigInt는 오류가 난다. 

Json에서 undefined가 반환되면, 해당 데이터는 무시됨을 뜻한다.

 

⚪ toJSON 메서드

Object안의 함수는 직렬화 했을 시, undefined이다.

하지만, toJson 함수를 사용 할 경우, 다른 프로퍼티들은 무시하면서, 함수만 직렬화 할 수 있다.

const obj = {
  x: 1,
  y: 2,
  toJSON: function () {
    return '직렬화 완료';
  }
}

console.log(
  JSON.stringify(obj)
);

⚪ 직렬화 필터하기

직렬화 할 때, 인자를 전달 함으로써, 어떠한 kye를 어떠한 value로 직렬화 할 것인지 정할 수 있다.

또한 가독성이 좋게 들여쓰기 기능을 줄 수도 있다.

⚫ 두번 째 인자 replacer 함수

인자를 key, value를 전달해서 필터링 할 수 있다.

const obj = {
  a: 1,
  b: '2',
  c: 3,
  d: '사',
  e: true,
  f: false,
  g: {a: 1},
  h: [1, 2, 3],
  i: 'pass'
};

const result = JSON.stringify(obj, (key, value) => {
  if (key && key < 'a' || key > 'h') {
    return undefined;
  }
  if (typeof value === 'number') {
    return value * 100;
  }
  return value;
})

console.log(result);

⭐ JSON에서 key를 가지고 필터링 할 경우에는, object에 대한 key를 전부 인식한다.

인자를 obj를 주었을 때, obj자체를 key로 인식하고, g또한 key이며 그 내부의 a또한 key로 인식한다.

h에서는 h또한 key이며, 0(인덱스)이 key이며 1을 value로 인식한다.

따라서, 위의 코드경우 g의 value안에서도 key와 value를 인식하고, key가 첫번째 조건인 a보다 작지 않기 때문에 반환이 된 것을 확인 할 수 있다.

반면에, h인 경우 h의 내부에는 인덱스 0...2를 key로 인식하는데, 조건에 충족하지 않기 때문에 빈 값이 출력 된 것을 확인 할 수 있다.

같은 이유로 key&&를 쓴 이유는, obj자체가 key가 되기 때문에 조건에 key가 만족하지 않아 처음부터 undefined가 나오는 것을 방지하기 위함이다.

 

함수를 작성해서 필터링 하는 방법 이외에도, 배열로 반환하고 싶은 키를 전달 해서 필터링 할 수 있다.

console.log(JSON.stringify(obj, ['a', 'b', 'c']));

 

⚫ 세번째 인자 인덴트

세번째 인자를 전달해서, 가독성 좋게 스페이스를 추가 해 직렬화 할 수 있다.

필터링을 하지 않을 경우, null을 전달 하면 된다.

const obj = {
  a: 1,
  b: '2',
  c: true,
  d: {a: 3},
  e: [1, 2, 3]
};

console.log(JSON.stringify(obj, null, 1));

 

⚪ 역직렬화 JSON.parse()

JSON 포맷을 JS형식으로 변환하는 메서드이다.

JSON화가 될 때 따옴표가 붙어서 된다. 따라서 반대로 했을 때는 따옴표가 없어진다는 것과 같기 때문에,

역직렬화를 할 때는 따옴표를 붙여준다.

문자열일 경우 따옴표 안에 따옴표를 붙여주고, JSON화 일 경우 Key에도 따옴표가 붙기 때문에 붙인다음 역직렬화한다.

[
  JSON.parse('1'),
  JSON.parse('"2"'),
  JSON.parse('"삼"'),
  JSON.parse('{"a":1}'),
  JSON.parse('[1, 2, 3]')
].forEach(i => console.log(i));

💡 JSON.stringify() 했을 때, 전체 객체에 대해 따옴표가 붙지만 그 내부의 객체에는 따옴표가 붙지 않았다.

하지만 key에는 따옴표가 붙는 다는 것을 명심하자.

 

⚪ 직렬화 필터하기

stringify처럼, parse도 인자를 전달 해서 필터링 할 수 있다.

const objStr = '{"a": 1,"b": "2","c": "삼","d": {"a": 1}, "e": [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);

단, 배열에 대한 키 필터링과 인덴트는 사용 할 수 없다.

 

⚪ 깊은 동결

freeze를 통해서 Object를 얕게 얼릴 수 있고, 재귀함수를 통해 깊은 동결을 할 수 있다.

하지만 재귀함수는 복잡하고 가독성이 떨어지기 때문에 그보다 더 간편한 방법으로 JSON을 사용한다.

JSON.stringify()후, JSON.parse()를 한다.

💡 JSON의 특징으로, Infinity, NaN, new Date(), BigInt, Symbol, 함수 에 대해 제한적이다.

 

⚫ structuredClone()

stringify후, parse한 깊은동결 과 같은 기능을 하는 메서드 이다.

단, 일부 브라우저에서만 지원한다는 단점이 있다.

new Date()와 BigInt는 지원 가능하다.

JSON에서 한정적인 다른 타입들은 똑같이 불가능하다. 

'TIL > JS' 카테고리의 다른 글

BigInt  (0) 2023.03.28
2, 8, 16진법과 비트 연산  (0) 2023.03.28
Symbol  (0) 2023.03.27
Object methods  (0) 2023.03.24
디스트럭쳐링 접근  (0) 2023.03.24