본문 바로가기
부트캠프 개발일기/Algorithm

22일차: JSON, 재귀함수 실습

by shyun00 2023. 3. 15.

❯ JSON

JSON(JavaScript Object Notation). 데이터 교환을 위해 만들어진 객체 형태의 포맷.

 

네트워크를 통해 어떤 객체를 다른 프로그램에게 전송한다고 가정해보자.

수신자와 발신자가 다른 프로그램을 사용할 경우 데이터가 제대로 전달되지 않을 수 있다.

따라서, 데이터가 정상적으로 전달되기 위해서는 (1) 수신자와 발신자가 같은 프로그램을 사용하거나 (2) 문자열처럼 범용적으로 읽을 수 있는 형태로 전달되어야한다.

 

이를 위해 사용하는 것이 JSON 형태를 사용하는 것이다.

JSON 구조

1. JSON 객체는 데이터 이름과 값의 쌍으로 이루어진다.
    "데이터이름" : 값 의 형태로 표시하며, 데이터 이름은 문자열이므로 항상 큰따옴표("") 와 함께 사용한다.

    데이터 값으로는 숫자, 문자열, 불리언, 객체, 배열, null 타입이 올 수 있다.

2. 데이터는 쉼표(,)로 나열된다.

3. 객체(Object)는 중괄호 ({})로 표현한다.

4. 배열(Array)는 대괄호 ([])로 표현한다.

 

자바에서는 jackson 라이브러리에서 제공하는 ObjectMapper 클래스를 통해 쉽게 JSON 형태로 변경할 수 있다.

<예시>

// 메시지를 담고 있는 데이터 message
Map<String, String> message = new HashMap<>(){{
      put("sender", "김코딩");
      put("receiver", "박해커");
      put("message", "밥먹을래?");
      put("createdAt", "2021-01-12,10:10:10");
    }};
    
// ObjectMapper를 활용한 직렬화
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(message);

System.out.println(json);
/*
{"createdAt":"2021-01-12,10:10:10","receiver":"박해커","sender":"김코딩","message":"밥먹을래?"}
*/

 

 

반대로, 아래와 같이 역직렬화도 가능하다.

ObjectMapper mapper = new ObjectMapper();
String json = "{\"createdAt\":\"2021-01-12,10:10:10\",\"receiver\":\"박해커\",\"sender\":\"김코딩\",\"message\":\"밥먹을래?\"}";

Map<String, String> deserializedData = mapper.readValue(json, Map.class);
System.out.println(deserializedData);
/*
{createdAt=2021-01-12,10:10:10, receiver=박해커, sender=김코딩, message=밥먹을래?}
*/

 

▼ 코드스테이츠 stringify 과제 코드.

결과물을 만드는데에만 신경쓴 느낌이다. JSON 출력 형태와 코드 흐름을 다시 그려보고 코드를 재작성해봐야겠다.

더보기
public String stringify(Object data) {

    //입력된 값이 문자열일 경우
    if (data instanceof String) {
        return String.format("\"%s\"", data.toString());
    }

    //입력된 값이 Integer일 경우
    else if (data instanceof Integer) {
        return data.toString();
    }

    //입력된 값이 Boolean일 경우
    else if (data instanceof Boolean) {
        return data.toString();
    }

    //입력된 값이 Object[]일 경우
    else if (data instanceof Object[]) {

        Object[] dataArray = (Object[]) data;
        if (dataArray.length == 0) return "[]";

        String answer = "";

        for (Object element : dataArray) {
            answer = answer + stringify(element).toString() + ",";
        }
        answer = answer.substring(0, answer.length() - 1);

        return String.format("[%s]", answer);
    }

    //입력된 값이 HashMap일 경우
    else if (data instanceof HashMap) {

        HashMap<Object, Object> dataHashMap = (HashMap<Object, Object>) data;
        if (dataHashMap.size() == 0) return "{}";

        Set<Map.Entry<Object, Object>> dataHashSet = dataHashMap.entrySet();

        Stream<Map.Entry<Object, Object>> dataStream = dataHashSet.stream();
        Object[] result = dataStream.map(el -> stringify(el.getKey()) + ":" + stringify(el.getValue()))
                .toArray();

        String answer = "";
        for (Object element : result) {
            answer = answer + element + ",";
        }
        answer = answer.substring(0, answer.length() - 1);

        return String.format("{%s}", answer);
    }

    //지정되지 않은 타입의 경우에는 "null"을 리턴합니다.
    else return "null";
}

과제를 작성하는데 꽤 많은 시간이 걸렸다. 재귀함수의 경우 정말 한번 생각이 꼬이기 시작하니 끝이 없이 꼬이고,

처음 작성하던것과 다른 방향으로 코드를 작성하고 있는 자신을 발견할 수 있었다.

우선 개념정리를 다시한번 하고 검색이나 레퍼런스코드 없이 처음부터 재작성하는 연습을 반복해야겠다.