JSON์ด๋, JSON(JavaScript Object Notation)์ ์ฝ์๋ก Javascript ๊ฐ์ฒด ๋ฌธ๋ฒ์ผ๋ก ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ํํํ๊ธฐ ์ํ ๋ฌธ์ ๊ธฐ๋ฐ์ ํ์ค ํฌ๋งท์ด๋ค.
๊ทธ๋ฌ๋ฉด ์ JSON์ ์์์ผ ํ ๊น?
์น์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ก์ ํด์ผํ ๋ ์ผ๋ฐ์ ์ผ๋ก JSON์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค. (์๋ฅผ๋ค์ด, ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์กํด์ผํ๋ ๊ฒฝ์ฐ)
JSON์ ์ด๋ป๊ฒ ์ฌ์ฉํด์ผ ํ ๊น?
JSON์ ๋ฌธ์์ด ํํ๋ก ์กด์ฌํ๋ค. Javascript ๊ฐ์ฒด ๋ฌธ๋ฒ์ ๋ฐ๋ฅด๋ ๋ฌธ์์ด์ด๊ธฐ ๋๋ฌธ์, ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์
์ธ ๋ฌธ์์ด, ์ซ์, ๋ฐฐ์ด, ๋ถ๋ฆฌ์ธ ๊ทธ๋ฆฌ๊ณ ๋ค๋ฅธ ๊ฐ์ฒด๋ค๋ ํฌํจํ ์ ์๋ค.
JSON ์ฌ์ฉ๋ฒ์?
๊ฐ๋จํ ์์๋ฅผ ์ดํด๋ณด๋ฉด์ ์ดํด๋ฅผ ํด๋ณด์.
const message = {
sender: "์ด์ฐ์ฑ",
receiver: "๋ค์ด๋ฒ",
message: "์ ๋ฅผ ๋ฐ๋ ค๊ฐ์ธ์!",
createdAt: "2021-02-15 21:08:10"
};
let transferableMessage = JSON.stringify(message);
console.log(transferableMessage);
// {"sender":"์ด์ฐ์ฑ","receiver":"๋ค์ด๋ฒ","message":"์ ๋ฅผ ๋ฐ๋ ค๊ฐ์ธ์!","createdAt":"2021-02-15 21:08:10"}
์ด๋ฐ์์ผ๋ก ์ฌ์ฉ๋ฒ์ ์ ๋ง ๊ฐ๋จํ๋ค. ๊ทธ๋ฆฌ๊ณ stringifyํ๋ ์ด ๊ณผ์ ์ ์ง๋ ฌํ(serialize)ํ๋ค๊ณ ํ๋ค.
Other notes
๊ทธ๋ ๋ค๋ฉด ๋ค์ ๊ฐ์ฒด๋ก ๋ณํ์?
์ด์ ๋ ๋ฌธ์์ด ๊ทธ ์์ฒด๋ก ๋๊ตฐ๊ฐ์๊ฒ ๊ฐ์ฒด ๋ด์ฉ์ ๋ณด๋ผ ์ ์๊ฒ ๋์๋ค. ๊ทธ๋ ๋ค๋ฉด ์์ ์๋ ์ด ๋ฉ์์ง๋ฅผ ์ด๋ป๊ฒ ๋ค์ ๊ฐ์ฒด๋ก ๋ง๋ค ์ ์์๊น?
๊ทธ ์ญํ ์ ํ๋ ๊ฒ์ด ๋ฐ๋ก parseํ๋ ์ด ๊ณผ์ ์ ์ญ์ง๋ ฌํ(deserialize)ํ๋ค๊ณ ํฉ๋๋ค.์ด๋ค.
let packet = {sender: "์ด์ฐ์ฑ", receiver: "๋ค์ด๋ฒ", message: "์ ๋ฅผ ๋ฐ๋ ค๊ฐ์ธ์!", createdAt: "2021-02-15 21:08:10"};
let obj = JSON.parse(packet);
console.log(obj);
/*
{
sender: "์ด์ฐ์ฑ",
receiver: "๋ค์ด๋ฒ",
message: "์ ๋ฅผ ๋ฐ๋ ค๊ฐ์ธ์!",
createdAt: "2021-02-15 21:08:10"
};
*/
parseํ๋ ์ด ๊ณผ์ ์ ์ญ์ง๋ ฌํ(deserialize)ํ๋ค๊ณ ํ๋ค.
์ด์ฒ๋ผ, JSON์ ์๋ก ๋ค๋ฅธ ํ๋ก๊ทธ๋จ ์ฌ์ด์์ ๋ฐ์ดํฐ๋ฅผ ๊ตํํ๊ธฐ ์ํ ํฌ๋งท์ด๋ฉฐ, ๋จ์ํ ์๋ฐ์คํฌ๋ฆฝํธ์์๋ง ์ฐ์ด๋ ๊ฒ์ด ์๋, ์ฌํ ๋ค๋ฅธ ์ธ์ด์์๋ ๋ฒ์ฉ์ ์ผ๋ก ์ฐ์ด๋ ์์ฃผ ์ ๋ช ํ ํฌ๋งท์ด๋ค.
๊ทธ๋ฌ๋ฉด ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฌ๊ท๋ฅผ ์ฌ์ฉํด์ JSON์ ๊ตฌํํด๋ณด์! :punch: :punch: :punch:
๋๋ ๋จผ์ ๋ฐฐ์ด(Array)๊ณผ ๊ฐ์ฒด(Object) ๊ทธ๋ฆฌ๊ณ ๋๋จธ์ง ํ์ ๋ค, ์ด๋ ๊ฒ ํฌ๊ฒ ์ธ๊ฐ์ง๋ก ๋ถ๋ฅ๋ฅผ ํด์ ์๊ฐ์ ํ๋ค.
์ธ์๋ฅผ ๋ฐ์์ ๋ ๋จผ์ number, null, boolean, string ํ์ ๋ค์ ๋ฌธ์์ด๋ก ๋ณํํด์ ๋ฐํํด์ฃผ์๋ค.
function stringifyJSON(obj) {
//TODO: recursive base
if (typeof obj === "number" || obj === null || typeof obj === "boolean") {
return `${obj}`;
} else if (typeof obj === "string") {
return `"${obj}"`; // ๋ฌธ์์ด์ ์๋ฐ์ดํ๋ฅผ ํ ๋ฒ ๋ ๋ถ์ฌ์ค์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๋ถ๋ฅํ๋ค.
}
๊ทธ ๋ค์์ ํ์ ์ด ๋ฐฐ์ด(Array)์ด๊ณ ๊ทธ ์์์ ๋น ๋ฐฐ์ด์ด๋, ์์๊ฐ ์๋๋ก ๋๋์ด์ฃผ์๋ค.
์์๊ฐ ์์ ๊ฒฝ์ฐ๋ ๋ชจ๋ ์์์ ์ ๊ทผ์ ํด์ผํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ์์์ ์ฌ๊ทํจ์๋ฅผ ์ ์ฉ์์ผ์ฃผ์๋ค. ๊ทธ ํ์ ๋ฌธ์์ด๋ก ๋ ์์๋ค์ ์๋ก์ด ๋ฐฐ์ด์ push๋ฅผ ํด์ฃผ์๋ค.
์ด ๋ถ๋ถ์ด ์ค๋ ๋ฐฐ์ด ๋ด์ฉ์ ํต์ฌ์ด๋ฉฐ, ๊ทธ๋ฆฌ๊ณ ์ง๊ธ ๊ตฌํํ๊ณ ์ ํ๋ JSON ํจ์์ ํต์ฌ์ด๋ค.
let resultArr = [];
if (Array.isArray(obj)) {
if (obj.length === 0) {
// ๋น ๋ฐฐ์ด์ธ์ง ํ์ธ
return "[]";
} else {
for (let i = 0; i < obj.length; i++) {
// ๋ชจ๋ ์์์ ์ฌ๊ทํจ์๋ฅผ ์ฌ์ฉํ๋ค. ์์๋ฅผ ๋ฌธ์์ด๋ก ๋ฐ๊พธ๊ธฐ ์ํด ์ฌ๊ท base๋ก ํฅํ๊ฒ ํ๋ค.
let result = stringifyJSON(obj[i]);
resultArr.push(result);
}
return `[${resultArr}]`; // ๋ฐฐ์ด์์ฒด๋ฅผ ๋ฌธ์์ด ํํ๋ก ๋ฐํํ๋ค.
}
}
์ด์ ๊ฐ์ฒด(Object)์ผ ๋๋ฅผ ์๊ฐํด์ผ ํ๋ค. ๊ฐ์ฒด๋ ๋ฐฐ์ด๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋จผ์ ๋น ๊ฐ์ฒด์ธ์ง ํ์ธ์ ํด์ฃผ์๋ค.
๊ทธ ํ์, ๊ฐ์ฒด์ value๊ฐ์ด function ์ด๊ฑฐ๋ undefined์ธ ๊ฒฝ์ฐ delete๋ฅผ ํด์ฃผ๊ณ ์ฌ๊ทํจ์๋ฅผ ์คํํ๋ค. (JSON ํจ์ ๊ตฌํ ๋ฌธ์ ์ค์ ํ๋ ์์)
๊ทธ๋ฆฌ๊ณ ๊ฐ์ฒด์ ๋ชจ๋ ํค์ ๊ฐ์ ๋ฐ๋ณต๋ฌธ์ผ๋ก ํ์ธํด์ฃผ๊ณ ๊ฐ ํค์ ๊ฐ์ ์ฌ๊ทํจ์๋ฅผ ์ ์ฉํ๋ค.
์ฝ๋๋ฅผ ๋ณด๋ฉด.
//TODO: Object
else {
let recursiveArr = [];
// ์ฌ๊ทํจ์๋ฅผ ์คํ์ํค๊ณ ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํด ํ ๋น
if (Object.keys(obj).length === 0) { // ๋น ๊ฐ์ฒด ํ์ธ
return "{}";
} else {
for (let key in obj) {
// ๋ชจ๋ ํค์ ๊ฐ์ ์ ๊ทผ
if (typeof obj[key] === "function" || obj[key] === undefined) {
delete obj[key];
stringifyJSON(obj);
// ํ์์๋ ๋ถ๋ถ์ ์ ๊ฑฐํ๊ณ ๋ค์ ์คํ(์ฌ๊ท)
} else {
// ๋ชจ๋ ํค์ ๊ฐ์ ํ์ธํ๊ณ ์ฌ๊ทํจ์๋ฅผ ํตํด ๋ฌธ์์ด๋ก ๋ณํ
let vals = stringifyJSON(obj[key]);
let keys = stringifyJSON(key);
let resultObj = keys + ":" + vals;
recursiveArr.push(resultObj);
// ๊ฐ์ ์ ์ฅํ๋ค.
}
}
}
return `{${recursiveArr}}`;
// ๊ฐ์ฒด ์์ฒด๋ฅผ ๋ฌธ์์ด๋ก ๋ฐํํ๋ค.
}
}
stringify-JSON ๊ตฌํ ์ฝ๋
function stringifyJSON(obj) {
//TODO: recursive base
if (typeof obj === "number" || obj === null || typeof obj === "boolean") {
return "" + obj;
} else if (typeof obj === "string") {
return `"${obj}"`;
}
//TODO: Array
let resultArr = [];
if (Array.isArray(obj)) {
if (obj.length === 0) {
return "[]";
} else {
for (let i = 0; i < obj.length; i++) {
let result = stringifyJSON(obj[i]);
resultArr.push(result);
}
return `[${resultArr}]`;
}
}
//TODO: Object
else {
let recursiveArr = [];
if (Object.keys(obj).length === 0) {
return "{}";
} else {
for (let key in obj) {
if (typeof obj[key] === "function" || obj[key] === undefined) {
delete obj[key];
stringifyJSON(obj);
} else {
let vals = stringifyJSON(obj[key]);
let keys = stringifyJSON(key);
let resultObj = keys + ":" + vals;
recursiveArr.push(resultObj);
}
}
}
return `{${recursiveArr}}`;
}
}
์ค๋์ JSON๋ฟ๋ง ์๋๋ผ ๊ธฐ์ ์ฉ ์ดํ๋ฆฌ์ผ์ด์ ์์ ํํ ๋ณผ ์ ์๋ tree-UI(ํธ๋ฆฌ๊ตฌ์กฐ)์ ๋ํด์ ๊ณต๋ถ๋ฅผ ํด๋ณด์๋ค.
์์ฑ๋ ๊ตฌ์กฐ๋ฅผ ์ดํด๋ณด๋ฉด
๊ธฐ๋ณธ์ ์ธ menu๋ ๋ค ์์ฑ์ด ๋์ด์๊ณ , ๋๋ ํธ๋ฆฌ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด์ค ํจ์๋ง ๊ตฌํํ๋ฉด ๋๋ ๋ฌธ์ ์๋ค.
ul์์์์ ๋ถ๋ชจ ์๋ฆฌ๋จผํธ๋ 4๊ฐ์ง (์๋ฃ, ์์, ๊ตฟ์ฆ, ์นด๋)li๊ฐ ์๊ณ , ๊ทธ ์์ input ํ๊ทธ์ spanํ๊ทธ ๊ทธ๋ฆฌ๊ณ ์์ ์๋ฆฌ๋จผํธ๋ก ul์ด ๋ ์๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.
์์ ์๋ฆฌ๋จผํธ๊ฐ ์์ผ๋ฉด ์ฌ๊ทํจ์๋ฅผ ์ฌ์ฉํ๊ณ , ์์ผ๋ฉด ๊ทธ๋๋ก ํ ์คํธ๋ฅผ ๋ฐํํ๋ ๊ตฌ์กฐ์ด๋ค.
๊ฐ์ฅ ์ค์ํ ๊ฒ์ ์์ ์์๊ฐ ์๋์ง, ์๋์ง๋ฅผ ๊ตฌ๋ถ์ง์ด์ผ ํ๋ค.
๋ง์ฝ ์์์์๊ฐ ์๋ค๋ฉด ์ฌ๊ทํจ์๋ฅผ ์จ์ฃผ์ด์ผ ํ๊ณ , ์๋ค๋ฉด ๊ทธ๋๋ก ๋ฐํํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๋จผ์ ์นดํ ๊ณ ๋ฆฌ (์๋ฃ, ์์, ๊ตฟ์ฆ, ์นด๋) 4๊ฐ์ง๋ฅผ ๋ ๋๋งํ 4๊ฐ์ li ์๋ฆฌ๋จผํธ๊ฐ ์์ด์ผ ํ๋ค.
์ด ๊ฒฝ์ฐ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํด๋ ๋์ง๋ง, ๋๋ forEach ๋ด์ฅํจ์๋ฅผ ์ฌ์ฉํ๋ค.
menu.forEach(el => {
if (el.type === "group") {
// ๋ชจ๋ 1์ฐจ์ ๊ฐ์ฒด๊ฐ type: "group" ์ผ๋ก ๋ฌถ์ฌ์์
let li = document.createElement("li");
currentNode.append(li);
...
๊ทธ๋ฆฌ๊ณ ์์์์๋ก input, span, ul ์ด๋ ๊ฒ 3๊ฐ์ง๊ฐ ์๋๋ฐ, ์ด๊ฒ๋ ๋ค ๋ง๋ค์ด์ค๋ค.
๊ทธ ํ
let input = document.createElement("input");
input.type = "checkbox";
li.append(input);
let span = document.createElement("span");
span.textContent = el.name;
li.append(span);
let ul = document.createElement("ul");
li.append(ul);
createTreeView(el.children, ul); // ์์ ์์๊ฐ ์์ผ๋ฉด๋ชจ๋ ์์๋ค์ ์ฌ๊ท์ ์ผ๋ก ์์ฑํ๋ค.
}
์ฌ๊ท๋ฅผ ๋๊ณ ๋ง์ฝ ์์ ์์๊ฐ ๋์ด์ ์๋ค๋ฉด? ํ ์คํธ๋ง ๋ฐํํ๋ค.
// ๋์ด์ ์์ ์์๊ฐ ์์ ๊ฒฝ์ฐ
else {
const li = document.createElement("li");
li.textContent = el.name;
currentNode.append(li);
}
tree-UI ๊ตฌํ ์ฝ๋
const root = document.getElementById("root");
function createTreeView(menu, currentNode) {
// TODO: createTreeView ํจ์๋ฅผ ์์ฑํ์ธ์.
menu.forEach(el => {
if (el.type === "group") {
let li = document.createElement("li");
currentNode.append(li);
let input = document.createElement("input");
input.type = "checkbox";
li.append(input);
let span = document.createElement("span");
span.textContent = el.name;
li.append(span);
let ul = document.createElement("ul");
li.append(ul);
createTreeView(el.children, ul);
} else {
const li = document.createElement("li");
li.textContent = el.name;
currentNode.append(li);
}
});
}
createTreeView(menu, root);
์ด์ ๋ด์ผ์ด๋ฉด ํ๋ฆฌ์ฝ์ค ๋ง์ง๋ง ๋ ์ด๋ค. ๋ง์ง๋ง๊น์ง ํ์ดํ ํ์!!
๐ ๋ด์ผ์ TIW(today I Will)
๋ ์จ API