JSON과 메서드

양주영·2021년 8월 30일
0

javascript

목록 보기
14/42

복잡한 객체를 다룰 때, 객체를 보내거나 출력하는 상황에서 객체는 문자열로 전환되어야 한다. 이러한 상황을 유연하게 대처하기 위해 json이 등장했다.

📍 JSON.stringify


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.stringify(student)를 호출하자 student가 문자열로 바뀌었다.
이렇게 변경된 문자열은 JSON으로 인코딩된, 직렬화 처리된, 문자열로 변환된, 결집된 객체라고 부른다. 객체는 이렇게 문자열로 변환된 후 비로소 네트워크를 통해 전송하거나 저장소에 저장할 수 있다.

JSON으로 인코딩된 객체는 일반 객체와 다른 특징을 보인다.

  • 문자열은 큰따옴표로 감싸야 한다. JSON에선 작은따옴표나 백틱을 사용할 수 없다.
  • 객체 프로퍼티 이름은 큰따옴표로 감싸야 한다.

JSON.stringify는 객체뿐만 아니라 원시값에도 적용할 수 있다.
적용할 수 있는 자료형은 아래와 같다.

  • 객체 { ... }
  • 배열 [ ... ]
  • 원시형:
    • 문자형
    • 숫자형
    • 불린형 값 true와 false
    • null

예시 :

// 숫자를 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]

JSON은 데이터 교환을 목적으로 만들어진 언어에 종속되지 않는 포맷이다. 따라서 자바스크립트 특유의 객체 프로퍼티는 JSON.stringify가 처리할 수 없다.

JSON.stringify 호출 시 무시되는 프로퍼티는 아래와 같다.

  • 함수 프로퍼티 (메서드)
  • 심볼형 프로퍼티 (키가 심볼인 프로퍼티)
  • 값이 undefined인 프로퍼티
let user = {
  sayHi() { // 무시
    alert("Hello");
  },
  [Symbol("id")]: 123, // 무시
  something: undefined // 무시
};

alert( JSON.stringify(user) ); // {} (빈 객체가 출력됨)

JSON.stringify중첩 객체도 알아서 문자열로 바꿔준다.

let meetup = {
  title: "Conference",
  room: {
    number: 23,
    participants: ["john", "ann"]
  }
};

alert( JSON.stringify(meetup) );
/* 객체 전체가 문자열로 변환되었습니다.
{
  "title":"Conference",
  "room":{"number":23,"participants":["john","ann"]},
}
*/

정리하자면,

  • 위와 같이 문자열로 변환된 후 객체는 네트워크를 통해 전송되거나 저장소에 저장될 수 있다.

  • JSON으로 인코딩된 객체는 문자열을 큰따옴표로만 감싸야 한다.

  • JSON의 프로퍼티 이름도 큰따옴표로 감싸야한다.

  • JSON.stringfy는 객체, 배열, 원시형(문자, 숫자, 불린, null)에도 적용할 수 있다.

  • 함수 프로퍼티(메서드), 심볼형 프로퍼티, 값이 undefined인 프로퍼티는 호출 시 무시된다.

  • JSON.stringfy는 중첩 객체도 문자열로 변환해준다.



📍 replacer로 원하는 프로퍼티만 직렬화하기


JSON.stringify 문법 :

let json = JSON.stringify(value[, replacer, space])

value
인코딩 하려는 값

replacer
JSON으로 인코딩 하길 원하는 프로퍼티가 담긴 배열. 또는 매핑함수 funtion(key, value)

space
서식 변경 목적으로 사용할 공백 문자 수

대다수의 경우 JSON.stringify엔 인수를 하나만 넘겨서 사용한다. 하지만 순환 참조를 다뤄야 하는 경우 같이 전환 프로세스를 정교하게 조정하려면 두 번째 인수를 사용한다.

replacer에 전달되는 함수(replacer 함수)는 프로퍼티 (키, 값) 쌍 전체를 대상으로 호출되는데, 반드시 기존 프로퍼티 값을 대신하여 사용할 값을 반환해야 한다. 특정 프로퍼티를 직렬화에서 누락시키려면 반환 값을 undefined로 만들면 된다.

아래 예시는 occupiedBy를 제외한 모든 프로퍼티의 값을 변경 없이 “그대로” 직렬화하고 있다. occupiedByundefined를 반환하게 해 직렬화에 포함하지 않은 것도 확인해 보자.

let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  participants: [{name: "John"}, {name: "Alice"}],
  place: room // meetup은 room을 참조합니다
};

room.occupiedBy = meetup; // room은 meetup을 참조합니다

alert( JSON.stringify(meetup, function replacer(key, value) {
  alert(`${key}: ${value}`);
  return (key == 'occupiedBy') ? undefined : value;
}));

/* replacer 함수에서 처리하는 키:값 쌍 목록
:             [object Object]
title:        Conference
participants: [object Object],[object Object]
0:            [object Object]
name:         John
1:            [object Object]
name:         Alice
place:        [object Object]
number:       23
*/


📍 space로 가독성 높이기


JSON.stringify(value, replacer, space)의 세 번째 인수 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
    }
}
*/


📍 커스텀 “toJSON”


toString을 사용해 객체를 문자형으로 변환시키는 것처럼, 객체에 toJSON이라는 메서드가 구현되어 있으면 객체를 JSON으로 바꿀 수 있다. JSON.stringify는 이런 경우를 감지하고 toJSON을 자동으로 호출해준다.

let room = {
  number: 23
};

let meetup = {
  title: "Conference",
  date: new Date(Date.UTC(2017, 0, 1)),
  room
};

alert( JSON.stringify(meetup) );
/*
  {
    "title":"Conference",
    "date":"2017-01-01T00:00:00.000Z",  // (1)
    "room": {"number":23}               // (2)
  }
*/
let room = {
  number: 23,
  toJSON() {
    return this.number;
  }
};

let meetup = {
  title: "Conference",
  room
};

alert( JSON.stringify(room) ); // 23

alert( JSON.stringify(meetup) );
/*
  {
    "title":"Conference",
    "room": 23
  }
*/

위와 같이 toJSONJSON.stringify(room)를 직접 호출할 때도 사용할 수 있고, room과 같은 중첩객체에도 구현하여 사용할 수 있다.



JSON.parse


JSON.parse를 사용하면 JSON으로 인코딩된 객체를 다시 객체로 디코딩 할 수 있다.

문법 :

let value = JSON.parse(str, [reviver]);

str
JSON 형식의 문자열

reviver
모든 (key,value) 쌍을 대상으로 호출되는 function(key, value)형태의 함수로 값을 변경시킬 수 있다.

💡 JSON은 주석을 지원하지 않는다.



reviver 사용하기


함수라면, 변환 결과를 반환하기 전에 이 인수에 전달해 변형한다.

let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';

let meetup = JSON.parse(str);

alert( meetup.date.getDate() ); // 에러!

meetup.date의 값은 Date 객체가 아니고 문자열이기 때문에 발생한 에러이다.
문자열을 Date로 전환해줘야할 때 reviver을 사용하면 된다.

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() ); // 이제 제대로 동작하네요!


참조 : https://ko.javascript.info/json

profile
뚜벅뚜벅

0개의 댓글