TIL 13) JSON & Tree UI

Hover·2023년 4월 12일
0

TIL

목록 보기
14/27

1. JSON.stringify & parse

정보를 담고있는 json은 객체 형태로 나타내진다.

const message = {
  sender:"mike",
  receiver:"lisa",
  message:"hello",
  createdAt:"2021-01-12 10:10:10"
}

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

따라서 다음과 같은 메소드를 사용한다.

JSON.stringify : 객체를 JSON으로 변환
JSON.parse : JSON을 객체로 변환

2. StringifyJSON.js

첫 번째 과제는 JSON.stringify를 구현하는 것이다.

const stringifiableObjects = [
  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 },
  // basic nesting
  { a: { b: "c" } },
  { a: ["b", "c"] },
  [{ a: "b" }, { c: "d" }],
  { a: [], c: {}, b: true },
];

위 배열을 전부 string형으로 바꿔주는 함수를 작성 해주면 된다.

stringifiableObjects.forEach(function (test) {
    const stringified = JSON.stringify(test)
    it(`객체는 문자열 "${stringified}"로 변환되어야 합니다`, function (done) {
      const expected = stringified;
      const result = stringifyJSON(test);
      expect(result).to.equal(expected);
      done();
    });
  });

밑에 for문을 보면 위 배열의 인덱스를 하나하나씩 순회하는 것을 볼 수 있다.

따라서, 조건에 맞게 함수를 작성하면 될 것 같다.


조건
1. Boolean은 string형으로 바꿔줘야한다.
2. String형은 다음과 같이 바꿔줘야 한다. > '"string"'
3. undefinedfunction은 변환해주지 않는다.
4. 객체와 배열은 다음과 같이 변환해준다 > '[1,"false",false]' , '{"x":5}'


function stringifyJSON(obj) {
  if (typeof obj === "boolean" || typeof obj === "number" || obj === null) {
    return `${obj}`;
  } // toString도 있지만 null은 바뀌지 않아서 ``를 사용
  if (typeof obj === "string") {
    return `"${obj}"`;
  }
  if (Array.isArray(obj)) {
    let newarr = [];
    for (let i = 0; i < obj.length; i++) {
      newarr.push(stringifyJSON(obj[i]));
    }
    return `[${newarr}]`;
  } // 새로운 배열에 값을 넣고 마지막에 string형으로 바꿔준다.
  if (typeof obj === "object") {
    let str = "";
    for (let key in obj) {
      if (
        typeof key === "function" ||
        typeof obj[key] === "function" ||
        key === "undefined" ||
        obj[key] === undefined
      ) {
        continue;
      }
      let newkey = stringifyJSON(key);
      let newvalue = stringifyJSON(obj[key]);
      str = str + `${newkey}:${newvalue},`;
    }
    return `{${str.slice(0, str.length - 1)}}`;
  }
}

3. TreeUI

const menu = [
  {
    type: "group",
    name: "음료",
    children: [
      {
        type: "group",
        name: "콜드 브루",
        children: [
          { type: "item", name: "나이트로 콜드 브루" },
          { type: "item", name: "돌체 콜드 브루" },
          { type: "item", name: "제주 비자림 콜드 브루" },
          { type: "item", name: "콜드 브루" },
        ],
      },
      {
        type: "group",
        name: "프라푸치노",
        children: [
          { type: "item", name: "애플 쿠키 크림 프라푸치노" },
          { type: "item", name: "더블 에스프레소 칩 프라푸치노" },
          { type: "item", name: "모카 프라푸치노" },
          { type: "item", name: "피스타치오 크림 프라푸치노" },
        ],
      },
      
      ......
      

위와 같은 배열을

이렇게 트리 형태로 바꿔줘야한다.

가장 상위 트리를 보면, 루트 밑에 크게 4종류의 트리가 있다.

이것은, 배열을 for문을 돌려서 작성해주면 편할 것 같다.

이후 자식노드의 구조를 보면 부모노드의 구조와 비슷하다. >> 재귀로 구현

다만, 자식노드가 없는 노드는 button이 없는 것을 보아 자식노드가 없는 노드는 버튼추가를 안 해도 될 것 같다.

const root = document.getElementById("root");
function createTreeView(menu, currentNode) {
  for (let i = 0; i < menu.length; i++) {
    let menuitem = document.createElement("li");
    if (menu[i].children !== undefined) {
      // 각 메뉴에 자식 노드가 있으면 -> radiobutton하고 내용 넣어야함
      const inputbutton = document.createElement("input");
      inputbutton.type = "checkbox";
      const spantext = document.createElement("span");
      spantext.textContent = menu[i].name;

      // 새로운 list 만들 ul
      // 자식노드의 자식노드 list
      const newul = document.createElement("ul");
      menuitem.append(inputbutton, spantext, newul); // li에 넣어줌
      currentNode.append(menuitem);

      createTreeView(menu[i].children, newul); // 자식 노드가 있으니까 재귀 한번 더돔
    } else {
      // 메뉴에 자식 노드가 없으면 -> li 엘리먼트 안에 단순히 이름만 표시
      menuitem.textContent = menu[i].name;
      currentNode.append(menuitem);
      // 자식 노드가 없으므로 재귀 돌릴 필요 없음.
    }
  }
}
createTreeView(menu, root);
profile
프론트엔드 개발자 지망생입니다

0개의 댓글