[Section2] 02. 자료구조와 알고리즘 기초 - 재귀 / 20230511
🧑🏻💻 TIL(Today I Learned)
✔️ StringifyJSON 과제
JSON이란?
➡️ JavaScript Object Notation의 줄임말, 데이터 교환을 위해 만들어진 객체 형태의 포맷
: 서로 다른 프로그램 사이에서 데이터를 교환하기 위한 포맷 (자바스크립트를 포함한 많은 언어에서 범용적으로 사용)
➡️ JSON으로 변환된 객체의 타입은 문자열
➡️ 오늘은 jackson 라이브러리에서 제공하는 ObjectMapper 클래스를 사용하여 JSON 형태로 변경하는 방법을 배움
📍 Jackson 라이브러리?
→ JSON 데이터 구조를 처리해주는 라이브러리
Map<String, String> message = new HashMap<>(){{
put("sender", "김코딩");
put("receiver", "박해커");
put("message", "밥먹을래?");
put("createdAt", "2021-01-12,10:10:10");
}};
- 메세지를 담고 있는 데이터
→ 데이터가 전송되려면 메세지를 보내는 발신자와 메세지를 받는 수신자가 같은 프로그램을 사용하거나 문자열처럼 범용적으로 읽을 수 있는 형태여야 함
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(message);
System.out.println(json);
/*
{"createdAt":"2021-01-12,10:10:10","receiver":"박해커","sender":"김코딩","message":"밥먹을래?"}
*/
// writeValueAsStsring 하는 과정을 '직렬화(serialize)'라고 함
- 발신자는 객체를 직렬화한 문자열을 누군가에게 보낼 수 있음, 수신자가 문자열 메세지를 다시 객체의 형태로 만들기 위해서는
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=밥먹을래?}
*/
- 직렬화된 JSON에 readValue 적용하면 다시 객체의 형태로 변환할 수 있음
→ readValue 적용하는 과정을 역직렬화(deserialize)라고 함
📍 이스케이프 문자(escape sequence)?
: 문자열 내에서 특수한 기능을 사용하는 문자
위 코드를 보면 아래와 같은 직렬화한 문자열을 볼 수 있는데 글자 사이사이에 역슬래시(\) 가 있음
"{\"createdAt\":\"2021-01-12,10:10:10\",\"receiver\":\"박해커\",\"sender\":\"김코딩\",\"message\":\"밥먹을래?\"}";
→ \" 글자 앞뒤로 이렇게 써주면 쌍따옴표를 포함해서 출력하겠다는 의미 (\"createdAt\")
→ 전체적인 문자열과 그 안에서 쌍따옴표를 포함해서 출력하겠다는 것을 구분하는 역할이라고 할 수 있음
"string" / "\"string\""
- 결과가 아래와 같이 나오는 것을 확인할 수 있음
🔎 JSON의 기본 규칙
➡️ 키 : 반드시 쌍따옴표를 붙여야 함
➡️ 문자열 값 : 반드시 쌍따옴표로 감싸야 함
➡️ 키와 값 사이, 그리고 키-값 쌍 사이에는 공백이 있어서는 안 됨
✔️ 재귀를 이용해 메서드 stringify 구현하기
➡️ 위에서 얘기했던 writeValue 메서드를 함수의 형태로 직접 구현하기 위해 재귀 사용하기
➡️ JSON은 대표적인 트리 구조, 전형적인 재귀 탐색이 가능한 구조(객체의 값으로 객체를 포함하는 구조)
👉🏻 입력된 값이 문자열일 경우
if(data instanceof String) {
return String.format("\"%s\"", data); //JSON 형식으로 출력하기 위한
}
👉🏻 입력된 값이 Integer일 경우
if(data instanceof Integer) {
return Integer.toString((Integer)data); // 명시적으로 타입 변환을 써주는 것이 좋음
}
👉🏻 입력된 값이 Boolean일 경우
if(data instanceof boolean) {
return String.valueOf(data); // 매개변수로 전달된 값을 문자열로 변환하는 역할
}
👉🏻 입력된 값이 Object[]일 경우
// 제일 처음 봐야할 것은 Object[] 타입이라는 것 결국은 모든 타입이 들어올 수 있음
// [1, 2, 3]
// [1, 2, true]
// [1,"true", true]
// 이런 식으로 어떻게 다양하게 나올지 모름
if(data instanceof Object[]) {
HashMap tmp = (HashMap)data;
String str = "";
Set<Map.Entry<Object, Object>> set = tmp.entrySet();
Iterator<Map.Entry<Object, Objectt> entryIterator = set.iterator();
while(entryIterator.hasNext()) {
Map.Entry<Object, Object> entry = entryIterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
str += String.format("%s:%s", stringify(key), stringify(value)) + ",";
}
String result = str.substring(0, str.length()- 1);
System.out.println(String.format("{%s}", result));
if(data instanceof Object[]) {
for(int i = 0; i < tmp.length; i++) {
tmp[i] = stringify(tmp[i]);
}
return Arrays.toString(tmp).replaceAll(" ", "").replaceAll("=", ":");
}
// 문제 자체가 완벽한 JSON 과는 좀 다르기 때문에 약간의 차이는 존재함
// 이해가 안 갈 때는 손파일링(?)으로 직접 넣어주자!
// 만약 [1, 2, 3] 이 data로 들어왔다고 한다면
if([1, 2, 3] instancof Object[]) {
for(int i = 0; i < tmp.length; i++) {
tmp[0] = stringify(1);
// 그럼 이 stringify(1)은 data == 0
// 즉, Integer 타입을 변환하는 경우의 조건에 걸려서 "" 이런 식으로 바뀌어서 들어감
// tmp[0] = 1;
tmp[1] = stringify(2);
tmp[2] = stringify(3);
// 이런 식으로 반복하면서 tmp에 문자열로 된 배열이 할당됨
// 그리고 Array.toString(tmp) 사용하여 문자열로 출력
// replaceAll() 메서드는 JSON은 띄어쓰기가 허용되지 않기 때문에 붙여쓰도록 해줌
}
👉🏻 입력된 값이 HashMap일 경우
if(data instanceof HashMap) {
HashMap tmp = (HashMap)data;
String str = "";
Set<Map.Entry<Object, Object>> set = tmp.entrySet();
Iterator<Map.Entry<Object, Object>> entryIterator = set.iterator();
while(entryIterator.hasNext()) { // 반복자 통해서 키와 값 꺼내기
Map.Entry<Object, Object> entry = entryIterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
str += String.format("%s:%s", stringify(key), stringify(value))+"," ;
}
String result = str.substring(0, str.length() - 1);
System.out.println(String.format("{%s}",result));
}
// HashMap은 순서가 없음 --> 하지만 데이터를 입력받은 순서대로 JSON 변환해서 나타내야 해!
// 그렇다면 결과를 받을 새로운 타입의 객체 생성하기 --> LinkedHashMap
HashMap<Object, Object> map = (HashMap<Object, Object>)data;
HashMap<Object,Object> result = new LinkedHashMap<>();
for(Map.Entry<Object, Object> entry : map.entrySet()) {
String key = stringify(entry.getKey());
String value = stringify(entry.getValue());
result.put(key, value);
}
return result.toString().replaceAll(" ","");
}
👉🏻 입력된 값이 null일 경우
return ObjectMapper(null);
오늘도 역시나 쉽지 않은 하루였다...... 페어 분이 아니었다면 하루 종일 삽질하고 있었을 듯 재귀 쉽지 않다. 아직은 생각의 깊이가 깊지 않아서 생각을 하고 적용을 해보는 게 많이 어렵다. 꾸준히 하다보면 익숙해지겠지만 과정은 늘 괴롭다. 코치님이랑 할 때는 이해가 가는데 혼자서 하면 또 어리둥절하는 부분도 많다. 몇 번이고 반복하고 반복해야지...... 😇
'SEB_BE_45 > 공부 정리' 카테고리의 다른 글
[Section2] 04. 자료구조와 알고리즘 - Graph, Tree 1 / 20230515 (1) | 2023.05.16 |
---|---|
[Section2] 03. 자료구조와 알고리즘 - Stack과 Queue / 20230512 (0) | 2023.05.15 |
[Section2] 01. 자료구조와 알고리즘 기초 - 재귀 (0) | 2023.05.10 |
[SEB BE] Section 1 회고 / 20230509 (0) | 2023.05.09 |
17. [Java] Thread, JVM, Garbage Collection / 20230508 (1) | 2023.05.09 |