목적: 재귀 파악
input 값을 JSON 형식으로 변환시키기.
undefined와 function은 JSON으로 생략시키거나
null로 변환할 것.
결과값 예시
9 -> 9,
true -> true,
'Hello world' -> "'Hello world'",
[1, 'false', false] -> '[1,"false",false]'
{ x: 5 } -> '{"x":5}'
function stringifyJSON(obj) {
// 간단한 출력부터 구현하기.
if (typeof obj === "boolean" || typeof obj === "number" || obj === null) return String(obj);
// 그냥 문자열로 나오면 되는 애들끼리 묶었다.
else if (typeof obj === "string") return `"${obj}"`;
// 문자열로 한 번 감싸서 출력.
케이스 순서로 따지면 다음이 배열인데,
조건문 내부 코드가 간단한 것부터 작성해 본다.
undefined와 함수를 미리 처리해 준다.
else if (typeof obj === "undefined" || typeof obj === "function") return "undefined";
else if (Array.isArray(obj)) {
let newArr = [];
for (let item of obj) {
newArr.push(stringifyJSON(item));
// 재귀 돌면서 push
}
return `[${newArr}]`;// 문자열로 감싸서 출력
}
배열 케이스 처리를 해 준다.
새 배열을 만든 후 반복문을 써야 계속 초기화가 되지 않는다...
왜요? 제가 그런 말도 안 되는 실수한 사람처럼 보이시나요?
-true-
else if (typeof obj === "object" && obj !== null) {
let str = "";
for (let key in obj) {
if (typeof obj[key] === "function" || obj[key] === undefined) {
return "{}";
}
let newKey = stringifyJSON(key);
// 재귀 돌아서 키 받기
let newValue = stringifyJSON(obj[key]);
// 다시 돌아서 선언된 키에 대한 값 받기
str = str + newKey + ":" + newValue + ",";
// 키: 값 형태 만들어 주고 쉼표로 분리
}
str = str.slice(0, -1); // 마지막 쉼표 삭제
return `{${str}}`; // 감싸서 출력
} else return undefined; // 예외 처리
}
객체 케이스와 else 처리.
이렇게 해서 테스트는 통과가 됐다.
하지만... 이러면 되겠지?
했던 부분이 안 돼서 수정하는 과정이 꽤 있었다.
약간 만만하게 본 듯...
재귀를 돌면서 키와 값을 따로 받아야 한다는 생각 자체를 못했다.
한번에 할 수 있는 방법은 없을까?
내용 추가.
테스트는 통과했지만 실제 동작과 다른 부분이 있어
셀프 코드 리뷰를 작성해 본다.
이전에 작성한 전체 코드. 주석을 제외했다.
function stringifyJSON(obj) {
if (typeof obj === "boolean" || typeof obj === "number" || obj === null) {
return String(obj);
} else if (typeof obj === "string") {
return `"${obj}"`;
}
else if (typeof obj === "undefined" || typeof obj === "function") {
return "undefined";
}
else if (Array.isArray(obj)) {
let newArr = [];
for (let item of obj) {
newArr.push(stringifyJSON(item));
}
return `[${newArr}]`;
}
else if (typeof obj === "object" && obj !== null) {
let str = "";
for (let key in obj) {
if (typeof obj[key] === "function" || obj[key] === undefined) {
return "{}";
}
let newKey = stringifyJSON(key);
let newValue = stringifyJSON(obj[key]);
str = str + newKey + ":" + newValue + ",";
}
str = str.slice(0, -1);
return `{${str}}`;
} else return undefined;
}
수정된 코드.
function stringifyJSON(obj) {
if (obj === null) {
return "null";
}
if (typeof obj === "string") {
return `"${obj}"`;
}
if (typeof obj === "number" || typeof obj === "boolean") {
return obj.toString();
}
if (Array.isArray(obj)) {
const elements = obj.map((element) => stringifyJSON(element));
return `[${elements.join(",")}]`;
}
if (typeof obj === "object") {
const properties = Object.keys(obj)
.map((key) => {
const value = stringifyJSON(obj[key]);
if (value !== undefined) {
return `"${key}":${value}`;
}
})
.filter((property) => property !== undefined);
return `{${properties.join(",")}}`;
}
return undefined;
}
그외