[자료구조/알고리즘] JSON, Tree UI, 재귀함수 과제
코테/자료구조, 알고리즘

[자료구조/알고리즘] JSON, Tree UI, 재귀함수 과제

반응형

JSON의 탄생 배경

JSON은 JavaScript Object Notation의 줄임말로, 데이터 교환을 위해 만들어진 객체 형태의 포맷입니다. 네트워크를 통해, 어떤 객체 내용을 다른 프로그램에게 전송한다고 가정하겠습니다. 이 객체 내용을 일종의 메신저 혹은 채팅 프로그램에서 쓰는 하나의 메시지 입니다.

 

const message = {
  sender: "김코딩",
  receiver: "박해커",
  message: "해커야 오늘 저녁 같이 먹을래?",
  createdAt: "2021-01-12 10:10:10"
}

 

메시지 객체가 전송 가능하려면, 메시지를 보내는 발신자와 메시지를 받는 수신자가 같은 프로그램을 사용하거나, 문자열처럼 범용적으로 읽을 수 있는 형태여야 합니다.

 

 

전송가능한 조건 (transferable condition)

  • 수신자(reciever)와 발신자(sender)가 같은 프로그램을 사용한다.
  • 또는, 문자열처럼 범용적으로 읽을 수 있어야 한다.

 

객체는 타입 변환을 이용해 String으로 변환할 경우 객체 내용을 포함하지 않습니다. JavaScript에서 객체에 메소드(message.toString())나 형변환(String(message))을 시도하면, [object Object] 라는 결과를 리턴합니다.

이 문제를 해결하는 방법은 객체를 JSON의 형태로 변환하거나 JSON을 객체의 형태로 변환하는 방법입니다. 이를 위한 메소드는 다음과 같습니다.

  • JSON.stringify : Object type을 JSON으로 변환합니다.
  • JSON.parse : JSON을 Object type으로 변환합니다.
  • JSON 공식 문서

 

let transferableMessage = JSON.stringify(message)
console.log(transferableMessage)  // `{"sender":"김코딩","receiver":"박해커","message":"해커야 오늘 저녁 같이 먹을래?","createdAt":"2021-01-12 10:10:10"}`
console.log(typeof(transferableMessage)) // `string`

message 객체를 JSON으로 변환하는 메소드 JSON.stringify

 

stringify하는 이 과정을 직렬화(serialize)한다고 합니다.

 

JSON으로 변환된 객체의 타입은 문자열입니다. 발신자는 객체를 직렬화한 문자열을 누군가에게 객체의 내용을 보낼 수 있습니다.

수신자는 이 문자열 메시지를 객체의 형태로 만드는 것은, JSON.stringify와 정반대의 작업을 수행을 하는 메소드 JSON.parse 를 사용할 수 있습니다.

 

 

let packet = `{"sender":"김코딩","receiver":"박해커","message":"해커야 오늘 저녁 같이 먹을래?","createdAt":"2021-01-12 10:10:10"}`

let obj = JSON.parse(packet)
console.log(obj)
/*
 * {
 * sender: "김코딩",
 * receiver: "박해커",
 * message: "해커야 오늘 저녁 같이 먹을래?",
 * createdAt: "2021-01-12 10:10:10"
 * }
 */
 console.log(typeof(obj))
 // `object`

JSON.parse를 적용하는 이 과정을 역직렬화(deserialize)한다고 합니다

 

 

[그림] 직렬화와 역직렬화 모식도

 

 

JSON은 서로 다른 프로그램 사이에서 데이터를 교환하기 위한 포맷입니다. 그리고 JSON 포맷은 자바스크립트을 포함한 많은 언어에서 범용적으로 사용하는 유명한 포맷입니다.

 

 

JSON의 기본 규칙

JSON을 얼핏 보기에 자바스크립트의 객체와 별반 다를 바가 없어 보이지만, 자바스크립트의 객체와는 미묘하게 다른 규칙이 있습니다.

  자바스크립트 객체 JSON
키는 따옴표 없이 쓸 수 있음 반드시 쌍따옴표를 붙여야 함
문자열 값 문자열 값은 어떠한 형태의 따옴표도 사용 가능 반드시 쌍따옴표로 감싸야 함

 

또한 JSON은 키와 값 사이, 그리고 키-값 쌍 사이에는 공백이 있어서는 안됩니다.

 

 

 

 

JSON 재귀

function stringifyJSON(obj) {
  if (obj === null) {
    return "null";
  }
  if (typeof obj === "number" || typeof obj === "boolean") {
    return String(obj);
  }
  if (typeof obj === "string") {
    return `"${obj}"`;
  }
  //obj가 배열인 경우
  if (Array.isArray(obj)) {
    const result = [];
    obj.forEach(function (element) {
      result.push(stringifyJSON(element))
    })
    return `[${result}]`;
  }
  //obj가 객체인 경우 (객체에는 배열, 객체 모두 포함되지만 배열인 경우보다 아래에 작성했으므로 배열은 제외된다.)
  if (typeof obj === "object") {
    let result = "";
    for (let key in obj) {
      if (obj[key] === undefined || typeof obj[key] === "function") {
        result = String(result);
      } else {
        result = result + `${stringifyJSON(key)}:${stringifyJSON(obj[key])},`;
      }
    }
    result = result.substr(0, result.length - 1);
    return `{${result}}`;
  }
};


  stringifyJSON는 JSON.stringify 함수를 실행했을 때와 같은 결과를 리턴해야 합니다
    ✓ 객체는 문자열 "9"로 변환되어야 합니다
    ✓ 객체는 문자열 "null"로 변환되어야 합니다
    ✓ 객체는 문자열 "true"로 변환되어야 합니다
    ✓ 객체는 문자열 "false"로 변환되어야 합니다
    ✓ 객체는 문자열 ""Hello world""로 변환되어야 합니다
    ✓ 객체는 문자열 "[]"로 변환되어야 합니다
    ✓ 객체는 문자열 "[8]"로 변환되어야 합니다
    ✓ 객체는 문자열 "["hi"]"로 변환되어야 합니다
    ✓ 객체는 문자열 "[8,"hi"]"로 변환되어야 합니다
    ✓ 객체는 문자열 "[1,0,-1,-0.3,0.3,1343.32,3345,0.00011999]"로 변환되어야 합니다
    ✓ 객체는 문자열 "[8,[[],3,4]]"로 변환되어야 합니다
    ✓ 객체는 문자열 "[[[["foo"]]]]"로 변환되어야 합니다
    ✓ 객체는 문자열 "{}"로 변환되어야 합니다
    ✓ 객체는 문자열 "{"a":"apple"}"로 변환되어야 합니다
    ✓ 객체는 문자열 "{"foo":true,"bar":false,"baz":null}"로 변환되어야 합니다
    ✓ 객체는 문자열 "{"boolean, true":true,"boolean, false":false,"null":null}"로 변환되어야 합니다
    ✓ 객체는 문자열 "{"a":{"b":"c"}}"로 변환되어야 합니다
    ✓ 객체는 문자열 "{"a":["b","c"]}"로 변환되어야 합니다
    ✓ 객체는 문자열 "[{"a":"b"},{"c":"d"}]"로 변환되어야 합니다
    ✓ 객체는 문자열 "{"a":[],"c":{},"b":true}"로 변환되어야 합니다
    ✓ 함수와 undefined는 stringify되지 않습니다

 

 

 

 

Tree UI

const root = document.getElementById('root');
// imperitive solution
function createTreeView(menu, currentNode) {
  for (let i = 0; i < menu.length; i++) {
    const li = document.createElement('li');
    if (menu[i].children) {
      const input = document.createElement('input');
      input.type = 'checkbox';
      const span = document.createElement('span');
      span.textContent = menu[i].name;

      const ul = document.createElement('ul');
      li.append(input, span, ul);
      currentNode.append(li);

      createTreeView(menu[i].children, ul);
    } else {
      li.textContent = menu[i].name;
      currentNode.append(li);
    }
  }
}
createTreeView(menu, root);
반응형