JSON

김수정·2020년 4월 22일
0
post-custom-banner

JSON

Javascript Object Notation은 값이나 객체를 나타내주는 범용 포맷입니다.
원래 자바스크립트에서 사용할 목적으로 만들어졌지만, 다른 언어에서도 라이브러리를 활용하여 다룰 수 있어서 데이터 교환 목적으로 많이 쓰입니다.

데이터를 JSON(문자열)으로 전환

JSON.stringify(value[, replacer, space])

  • value:인코딩 하려는 값
  • replacer: JSON으로 인코딩하길 원하는 프로퍼티가 담긴 배열
  • space: 서식 변경 목적으로 사용할 공백 문자 수

활용처

네트워크를 통해 객체를 어딘가에 보낼 때
로깅 목적으로 객체를 출력할 때

특징

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
}
*/

이제 stringify의 인수들의 사용법을 하나씩 살펴봅시다.

value

value는 stringify의 대상입니다.

(1) JSON은 언어에 종속되지 않는 포맷이므로 원시값에도 적용할 수 있지만 자바스크립트만의 특유한 객체 프로퍼티는 처리하지 못합니다. 그 종류는 아래와 같습니다.

  • 함수 프로퍼티(메서드)
  • 심볼형 프로퍼티 (키가 심볼인 프로퍼티)
  • 값이 undefined인 프로퍼티

(2) 중첩 객체도 알아서 문자열로 바꿔주지만 순환 참조는 에러가 납니다.

replacer

replacer는 json으로 인코딩하길 원하는 프로퍼티만 담은 배열. 또는 매핑 함수 function(key, value)
아래 예시처럼 두번째 인수에 배열로 넘겨준 값이 반환된 객체의 프로퍼티로 나왔습니다. 정체는 문자열이지만요.

let room = {
  number: 23
};

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

room.occupiedBy = meetup; // room references meetup
alert( JSON.stringify(meetup, ['title', 'participants']) );
// {"title":"Conference","participants":[{},{}]}

그런데 participants 의 참조형 데이터의 프로퍼티들이 들어오지 못했죠. 이 것들도 다 replacer의 배열에 넣어주어도 되고,
좀 더 직관적이고 쉽게 매핑 함수로 처리할 수도 있습니다.
매핑함수는 프로퍼티 (키, 값)쌍 전체를 대상으로 호출되고,
반드시 기존 프로퍼티 값을 대신하여 사용할 값을 반환해야 하고,
프로퍼티를 직렬화에서 누락시키려면 반환 값을 undefined로 하면 됩니다.

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;
})); // {"title":"Conference","participants":[{"name":"John"},{"name":"Alice"}],"place":{"number":23}}

/* 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

세 번째 인수는 공백 문자 수입니다. 객체 정렬할 때 정렬을 예쁘게 해줍니다. 가독성 측면에서 사용합니다.

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
    }
}
*/

custom toJSON

객체에 이미 toJson메서드가 있었다면, JSON.stringify는 이를 감지하여 그 원리에 맞게 문자열화 해줍니다.

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
  }
*/

JSON(문자열)을 원래형으로 전환

JSON.parse(str, [revivier]) 디코딩.

  • str: JSON형식의 문자열
  • revivier: 모든 key, value 쌍을 대상으로 호출되는 function(key, value)형태의 함수로 값을 변경시킬 수 있습니다.

JSON은 위에서 말했든 문자열 키나 값은 전부 큰 따옴표로 감싸야 하고, 주석을 지원하지 않습니다.

revivier

키 값만 맞다면 중첩객체여도 상관 없습니다.

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() ); // 에러가 나지 않음!
profile
정리하는 개발자
post-custom-banner

0개의 댓글