[SEB FE] Section3 unit 1 재귀 - JSON.stringify

동화·2022년 10월 21일
1

코드스테이츠

목록 보기
23/32
post-custom-banner

  • JSON 구조가 재귀 함수를 사용할 수 있는 트리 구조임을 이해할 수 있다.
  • JSON.stringifyJSON.parse 가 serialize, deserialize라는 것을 이해할 수 있다.
  • JSON.stringifyJSON.parse 를 사용하여 자바스크립트 값과 JSON을 넘나들 수 있다.
  • JSON에 재귀 호출을 사용할 때, 어디에 사용해야 할지 이해할 수 있다.

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


직렬화, 역직렬화

let transferableMessage = JSON.stringify(message)

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

console.log(typeof(transferableMessage))
// `string`

-> 직렬화(serialize)한다.


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`

-> 역직렬화(deserialize) 한다.


JSON 기본규칙

자바스크립트 객체JSON
키는 따옴표 없이 쓸 수 있음
{ key : "property" }
반드시 쌍따옴표를 붙여야 함
'{"key":"property"}'
문자열 값작은따옴표도 사용 가능
{ "key" : 'property' }
반드시 큰따옴표로 감싸야 함
'{"key":"property"}'
키와 값 사이 공백사용 가능
{"key" : 'property'}
사용 불가능
'{"key":"property"}'
키-값 쌍 사이 공백사용 가능
{ "key":'property', num:1 }
사용 불가능
'{"key":"property","num":1}'





template literal

  • 표현식과 문자열 삽입, 여러 줄 문자열 등 다양하고 편리한 기능을 제공하는 문법
  • 백틱(`)을 이용해서 감싸주며, 표현식은 ${변수}로 나타내고, 줄 띄어쓰기가 가능하다.
let obj = [1,2,3]

${obj} 안에 객체(배열 또는 진짜 객체)를 입력받는 경우, 객체의 문자열로 변환하여 대입한다.

obj가 배열인 경우에는, ${obj} 처럼 template literal을 사용해도
겉에 '[1,2,3]' 이러한 결과 가 나오지 않는다.
template literal이 붙는 순간,
배열([,])이 걷히고 그 요소에 문자열이 있으면 그 요소에 ''한 번 붙은 값이 나오게 된다.

let obj = ["1",2,3];
`${obj}` = "1,2,3" ; //중첩이 몇번이 되어도 다 벗겨지고 스트링화

나중에 [${}] 이러한 작업을 하기 위해, 즉
template literal이 한 번 더 붙어야 하기 때문에 문자열을 한 번 더 중첩시켜준다.
그리고 []브라켓으로 감싸 배열로 만들어준다 (빈 배열인 경우를 위해)

마지막으로 배열이 걷히고, 문자열이 1겹 걷히고 []브라켓을 추가로 넣어준다.
그러면 obj에 ''리터럴이 붙은형태인 '[1,2,3]'이 출력된다.

➡️ 템플릿 리터럴은 자료형을 문자열로 바꾸는 거라 배열에 템플릿 리터럴을 하는 건 배열에 toString을 하는 거랑 마찬가지!


과제

1. JSON.stringify

function stringifyJSON(obj) {
  // obj 처리 타입 종류 : boolean, string, array, object, null, number
  if (typeof obj === 'boolean' || typeof obj === 'number') { // Boolean or number가 input으로 주어졌을 경우
    return `${obj}`        // stringifyJSON(true); -> 'true'
  }
  if (typeof obj === 'string') { //  String이 input으로 주어졌을 경우
    return `"${obj}"`      // stringifyJSON('foo'); -> '"foo"'
  }
  if (obj === null) {  
    return 'null'
  }

  if (Array.isArray(obj)) {     // Array가 input으로 주어졌을 경우
    let result = [];
    for (let i = 0; i<obj.length; i++) {
      result.push(stringifyJSON(obj[i]))  
    } return `[${result}]` // stringifyJSON([1, 'false', false]); -> '[1,"false",false]'
  }

  // 객체에는 배열, 객체가 모두 포함되지만 배열인 경우보다 아래에 작성하였으므로 배열은 제외.
  if (typeof obj === 'object') {  // obj 가 객체인 경우
    let result = '';
    for (let key in obj) {
      if (obj[key] === undefined || typeof obj[key] === 'function') { // - undefined, function이 주어졌을 경우
        delete obj[key]
        stringifyJSON(obj)
      } else {
        result += `${stringifyJSON(key)}:${stringifyJSON(obj[key])},`
      }
    }
    result = result.slice(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되지 않습니다.



2. Tree UI

// TODO: createTreeView 함수를 재귀(자기 자신을 계속 부르게 함)호출하여 테스트케이스를 통과하세요.
// GOAL: 최종 결과가 resut.html와 같은 모습으로 나와야 합니다.

// 데이터 구조
// menu[0]은 음료 메뉴판 .children = [ 콜드브루, 프라푸치노, 블렌디드, 티, 주스]
// menu[1]은 음식 .children = [ 빵, 케이크, 샌드위치, 과일, 스낵, 아이스크림 ]
// menu[2]은 굿즈 .children = [ 머그, 텀블러, 악세사리 ]
// menu[3]은 카드 .children = [ 10000원권, 30000원권, 50000원권, 100000원권 ]

// menu[i].children = [ {type: 'item', name: 이름}, {type: 'item', name: 이름} ]


const root = document.getElementById('root');
function createTreeView(menu, currentNode) {
  for (let i = 0; i < menu.length; i++) {
    const li = document.createElement('li')

    if (menu[i].children) { // children 요소가 존재할 경우
      const input = document.createElement('input')
      input.type = 'checkBox'
      const span = document.createElement('span')
      span.textContent = menu[i].name  // ''씌우면 안됨
      // const makeInput = document.createElement("input");
      // makeInput.setAttribute("type", "checkbox");

      const ul = document.createElement('ul')
      // ↓ li 안에 input, span, ul 한꺼번에 넣어주기
      li.append(input, span, ul)
      currentNode.append(li)

      // 만든 ul에 자식요소를 붙이기 위해 재귀함수 호출
      createTreeView(menu[i].children, ul)
    }


  else {    // children 요소가 없을 때
    // ↓ li 태그 안에 'name' 값 넣어주기
    li.textContent = menu[i].name
    currentNode.append(li)
    }

  }
}

createTreeView(menu, root);

// 트리 상 -> 하 만드는 구조
// createTreeView(menu, currentNode) = currentNode 태그 안에 append로 ul 이나 li를 추가해주는 함수
// - 자식이 있으면 li에 ul 추가 재귀함수 호출, 없으면 li만 currentNode에 추가해준다
// 처음에 createTreeView(menu, root) 선언하기 때문에 첫 번째 currentNode는 ul #root가 됨
// 그 다음에는 createTreeView(menu[i].children, ul)로 재귀함수를 호출하여, ul에 li가 추가되게 만든다.

⁉️ currentNode 역할

추후 만들 li를 묶는 ul

⁉️ ul #root

맨 위에 선언된 루트 노드.
===> const root = document.getElementById('root')
처음에 menu가 들어가면 menu에 자식 노드들이 있는데, 얘들을 붙여부려면 본인 li에 ul을 append해주고 거기에 붙여주어야 하니까
재귀함수를 호출 한다
createTreeView(menu[i].children, 요기)
맨 처음 재귀함수가 호출될 때, '요기'에 들어가는 노드는 root 노드

post-custom-banner

0개의 댓글