stringify: Object Type을 JSON으로 변환
parse: JSON을 Object Type으로 변환
이것을 직렬화(Serialized → stringify), 역직렬화(Deserialized → parse)라고도 부른다.
JSON 기본규칙
재귀함수를 이용한 JSON.stringify 코드 (미완성)
function stringifyJSON(obj) {
// your code goes here
if (typeof obj === "boolean" || typeof obj === "number" || obj === null) {
return String(obj);
}
if (Array.isArray(obj)) {
let resultArr = [];
for (let i of obj) {
// i가 배열인 경우와 아닌경우, 배열인 경우 재귀함수사용 아닐시 그대로 리턴
let returnArr = [];
if (!Array.isArray(i)) {
// 배열이 아닌 경우
if (typeof i === "string") {
// 배열의 요소가 문자열인 경우
resultArr.push(`"${i}"`);
} else {
// 배열의 요소가 문자열이 아닌 경우
resultArr.push(`${i}`);
}
} else {
// 배열인 경우
returnArr = stringifyJSON(i); // 리턴시 반복문 종료
}
if (returnArr.length !== 0) {
resultArr.push(returnArr);
}
}
return `[${resultArr}]`; // 배열을 리턴했지만, 문자열 형태로 리턴됨.
}
if (typeof obj === "string") {
return `"${obj}"`;
}
if (typeof obj === "object" && !Array.isArray(obj)) {
let sumStr = "";
let newObj = "";
if (Object.keys(obj).length === 0) return "{}";
for (let i = 0; i < Object.keys(obj).length; i++) {
let returnObj = "";
if (typeof Object.values(obj)[i] === "boolean" || Object.values(obj)[i] === null) {
sumStr += `"${Object.keys(obj)[i]}":${Object.values(obj)[i]},`;
} else if (typeof Object.values(obj)[i] === "object") {
returnObj = stringifyJSON(Object.values(obj[i])); //{"b": "c"}
} else {
sumStr += `"${Object.keys(obj)[i]}":"${Object.values(obj)[i]}",`;
}
if (returnObj !== "") {
sumStr += `"${Object.keys(obj)[i]}":${returnObj},`;
}
newObj = `{${sumStr.slice(0, sumStr.length - 1)}}`;
}
return newObj;
}
}
여기까지 구현했는데 Object에서 재귀함수를 쓰는 부분에서 막혀버렸다. 자꾸 아래와 같은 오류가 뜬다.
TypeError: Cannot convert undefined or null to object
at Function.values (<anonymous>)
at stringifyJSON (src/stringifyJSON.js:74:42)
at Context.<anonymous> (spec/stringifyJSONSpec.js:48:22)
at processImmediate (node:internal/timers:464:21)
⇒ 이 오류는 Object.keys().length에서 Object값을 제대로 못넣어줘서 그렇게 된다고 하는데 난감하다,, 재귀함수에 된통 당해버렸다. 요것은 주말에 다시 복기하면서 완벽히 풀어 볼 예정이다.
const menu = [
{
type: "group",
name: "음료",
children: [
{
type: "group",
name: "콜드 브루",
children: [
{ type: "item", name: "나이트로 콜드 브루" },
{ type: "item", name: "돌체 콜드 브루" },
{ type: "item", name: "제주 비자림 콜드 브루" },
{ type: "item", name: "콜드 브루" },
],
},
//메뉴는 너무 길어 이정도에서 생략,, 음료와 같은 객체가 배열에 총 4개가 들어있다.
const root = document.getElementById("root");
function createTreeView(menu, currentNode) {
// for문을 통해 menu 배열을 돌면서 name값을 li.textcontent
// 자식 노드가 있는 데이터의 경우, li 엘리먼트 아래에 자식 노드를 렌더링할 새로운
// ul이 존재해야 합니다
let createChildNode;
for (let i = 0; i < menu.length; i++) {
const liMaker = document.createElement("li");
currentNode.appendChild(liMaker);
if (!menu[i].children) {
liMaker.textContent = menu[i].name;
} else {
const spanMaker = document.createElement("span");
const inputMaker = document.createElement("input");
inputMaker.setAttribute("type", "checkbox");
liMaker.appendChild(inputMaker);
liMaker.appendChild(spanMaker);
spanMaker.textContent = menu[i].name;
const ulMaker = document.createElement("ul");
liMaker.appendChild(ulMaker);
createChildNode = createTreeView(menu[i].children, ulMaker);
}
}
}
createTreeView(menu, root);
완성본
Tree-ui와 같이 실전에서 쓸법한 문제를 푸니까 어제보다는 재귀함수의 역할이 좀 더 와닿는 것 같았다. 특히 어려운 부분이 for문 안에서 재귀함수를 구현할 때 return 문으로 빼는게 아닌 변수로 값을 담아서 리턴을 해야하는데 이 부분이 풀려고 하는 문제마다 생각을 많이 요하는 부분이라 시간 소모가 많았다.
그래도!! 그만큼 성취감이 크게 주어졌다.