Gson TypeToken 개념 문제 (문제편)
문제 1: 기본 개념 (난이도: ★☆☆)
다음 중 TypeToken이 필요한 이유로 가장 적절한 것은?
- JSON 파싱 속도를 향상시키기 위해 ***** 2. Java의 Type Erasure로 인해 런타임에 제네릭 타입 정보가 사라지기 때문에 -> 이거
- 메모리 사용량을 줄이기 위해
- 스레드 안전성을 보장하기 위해
문제 2: 코드 분석 (난이도: ★★☆)
다음 코드에서 잘못된 부분을 찾아 수정하시오.
String json = "[\\"apple\\", \\"banana\\", \\"cherry\\"]";
Gson gson = new Gson();
// 잘못된 코드
List<String> fruits = gson.fromJson(json, List.class);
수정을 해 보았다~~
Type listType = new TypeToken<List<String>>(){}.getType();
List<String> fruits = gson.fromJson(json, listType);
List.class는 제네릭 타입 정보를 잃어버림 List로 처리하는데 그러면 String이 아닌 다른 객체로 변형될 수 있어버림~
문제 3: getType() 메서드 이해 (난이도: ★★☆)
다음 코드의 실행 결과를 예측하시오.
TypeToken<List<String>> token1 = new TypeToken<List<String>>(){};
TypeToken<List<Integer>> token2 = new TypeToken<List<Integer>>(){};
Type type1 = token1.getType();
Type type2 = token2.getType();
System.out.println("type1.equals(type2): " + type1.equals(type2));
System.out.println("type1 클래스: " + type1.getClass().getSimpleName());
System.out.println("type1 toString: " + type1);
getType()은 내부적으로 제네릭 파라미터까지 비교한다고 함 List과 List는 다르다고 판단
문제 4: Type 인터페이스 심화 (난이도: ★★★)
다음 코드에서 각 Type 객체가 어떤 구체적인 클래스의 인스턴스인지 예측하고, 그 이유를 설명하시오.
// Case 1: 단순 클래스
Type simpleType = String.class;
// Case 2: 제네릭 타입
Type genericType = new TypeToken<List<String>>(){}.getType();
// Case 3: 배열 타입
Type arrayType = String[].class;
// Case 4: 와일드카드 타입
Type wildcardType = new TypeToken<List<? extends Number>>(){}.getType();
System.out.println("Case 1: " + simpleType.getClass().getSimpleName());
System.out.println("Case 2: " + genericType.getClass().getSimpleName());
System.out.println("Case 3: " + arrayType.getClass().getSimpleName());
System.out.println("Case 4: " + wildcardType.getClass().getSimpleName());
모르겠길래 돌렸어요~
package kice4;
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
import java.util.List;
public class Main {
public static void main(String[] args) {
// Case 1: 단순 클래스
Type simpleType = String.class;
// Case 2: 제네릭 타입
Type genericType = new TypeToken<List<String>>(){}.getType();
// Case 3: 배열 타입
Type arrayType = String[].class;
// Case 4: 와일드카드 타입
Type wildcardType = new TypeToken<List<? extends Number>>(){}.getType();
System.out.println("Case 1: " + simpleType.getClass().getSimpleName());
System.out.println("Case 2: " + genericType.getClass().getSimpleName());
System.out.println("Case 3: " + arrayType.getClass().getSimpleName());
System.out.println("Case 4: " + wildcardType.getClass().getSimpleName());
}
}
결과
Case 1: Class
Case 2: ParameterizedTypeImpl
Case 3: Class
Case 4: ParameterizedTypeImpl
문제 5: getParameterized() 기본 사용법 (난이도: ★★☆)
다음 두 코드가 동일한 결과를 만드는지 확인하고, getParameterized() 메서드의 장점을 설명하시오.
// 방법 1: 전통적인 TypeToken 사용
Type type1 = new TypeToken<List<String>>(){}.getType();
// 방법 2: getParameterized() 사용
Type type2 = TypeToken.getParameterized(List.class, String.class).getType();
System.out.println("두 타입이 같은가? " + type1.equals(type2));
결과
두 타입이 같은가? true
Gson에서는 Java의 Type Erasure 때문에 제네릭 타입을 구분할 수 없음
TypeToken 또는 TypeToken.getParameterized() 를 사용하여 정확한 타입 정보를 만들어야 함~
⇒ 내부적으로 거의 같은 Type 객체를 생성하므로 결과는 true
getParameterized()
com.google.gson.reflect.TypeToken 클래스에서 제공하는 static 메서드
제너릭 타입의 Type 객체를 생성한다~
List<String> , Map<Sting,Integer> 같은 제너릭 타입 정보를 런타임에도 유지하도록 만들어줌
장점
1. 가독성
Type type = TypeToken.getParameterized(List.class, String.class).getType();
→ 한눈에 List<String> 구조라는 게 보임
Type type = new TypeToken<List<String>>(){}.getType();
→ 클래스 안에 중괄호가 들어가 가독성 떨어짐
2. 코드 간결
TypeToken.getParameterized(Map.class, String.class, Integer.class).getType();
→ 중첩 타입도 한 줄에 표현 가능
new TypeToken<Map<String, Integer>>(){}.getType();
→ 간단해 보이지만 중첩되면 불편함
복잡할수록 더 좋은듯
Type type = TypeToken.getParameterized(
Map.class,
String.class,
TypeToken.getParameterized(List.class, Integer.class).getType()
).getType();
new TypeToken<Map<String, List<Integer>>>(){}.getType();
문제 6: 동적 타입 생성 (난이도: ★★★)
다음 메서드를 완성하시오. 이 메서드는 런타임에 클래스 정보를 받아서 List<T> 타입의 TypeToken을 생성해야 합니다.
public static <T> Type createListType(Class<T> elementClass) {
// 여기를 완성하시오
return TypeToken.getParameterized(List.class, elementClass).getType();
}
// 사용 예시
Type stringListType = createListType(String.class);
Type integerListType = createListType(Integer.class);
문제 7: 복잡한 중첩 타입 (난이도: ★★★)
Map<String, List<User>> 타입을 getParameterized()를 사용해서 생성하는 코드를 작성하시오.
public class User {
private String name;
private int age;
}
// getParameterized()를 사용해서 Map<String, List<User>> 타입 생성
Type listOfUser = TypeToken.getParameterized(List.class, User.class).getType();
Type mapOfList = TypeToken.getParameterized(Map.class, String.class, listOfUser).getType();
문제 8: Type 타입 검사 (난이도: ★★★)
주어진 Type 객체가 어떤 종류의 타입인지 판별하는 메서드를 작성하시오.
public static void analyzeType(Type type) {
// type이 다음 중 어떤 것인지 판별하고 출력하시오:
// 1. Class (단순 클래스)
// 2. ParameterizedType (제네릭 타입)
// 3. GenericArrayType (제네릭 배열)
// 4. WildcardType (와일드카드)
// 5. TypeVariable (타입 변수)
if (type instanceof Class) {
System.out.println("Class (단순 클래스)");
} else if (type instanceof ParameterizedType) {
System.out.println("ParameterizedType (제네릭 타입)");
} else if (type instanceof GenericArrayType) {
System.out.println("GenericArrayType (제네릭 배열)");
} else if (type instanceof WildcardType) {
System.out.println("WildcardType (와일드카드)");
} else if (type instanceof TypeVariable) {
System.out.println("TypeVariable (타입 변수)");
} else {
System.out.println("Unknown type");
}
}
// 테스트할 타입들
Type[] testTypes = {
String.class,
new TypeToken<List<String>>(){}.getType(),
new TypeToken<List<? extends Number>>(){}.getType(),
new TypeToken<T[]>(){}.getType() // T는 타입 변수
};
결과
package kice4;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import com.google.gson.reflect.TypeToken;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 테스트할 타입들
Type[] testTypes = {
String.class,
new TypeToken<List<String>>(){}.getType(),
new TypeToken<List<? extends Number>>(){}.getType()
};
for (Type type : testTypes) {
System.out.println("분석 대상: " + type.getTypeName());
analyzeType(type);
System.out.println();
}
}
public static void analyzeType(Type type) {
if (type instanceof Class) {
System.out.println("Class (단순 클래스)");
} else if (type instanceof ParameterizedType) {
System.out.println("ParameterizedType (제네릭 타입)");
} else if (type instanceof GenericArrayType) {
System.out.println("GenericArrayType (제네릭 배열)");
} else if (type instanceof WildcardType) {
System.out.println("WildcardType (와일드카드)");
} else if (type instanceof TypeVariable) {
System.out.println("TypeVariable (타입 변수)");
} else {
System.out.println("Unknown type");
}
}
}
분석 대상: java.lang.String
Class (단순 클래스)
분석 대상: java.util.List<java.lang.String>
ParameterizedType (제네릭 타입)
분석 대상: java.util.List<? extends java.lang.Number>
ParameterizedType (제네릭 타입)
문제 9: getParameterized() 고급 활용 (난이도: ★★★)
다음 제네릭 메서드에서 getParameterized()를 사용해서 동적으로 API 응답 타입을 처리하는 코드를 완성하시오.
public class ApiClient {
public static class ApiResponse<T> {
private boolean success;
private T data;
private String message;
// getter, setter 생략
}
// 이 메서드를 완성하시오
public <T> ApiResponse<T> request(String url, Class<T> responseClass) {
// JSON 응답을 받았다고 가정
String jsonResponse = "...";
Gson gson = new Gson();
// getParameterized()를 사용해서 ApiResponse<T> 타입 생성
Type type = TypeToken.getParameterized(ApiResponse.class, responseClass).getType();
// 그리고 JSON을 파싱하여 반환
return new Gson().fromJson(jsonResponse, type);
}
}
고재원
public static <T> ApiResponse<T> request(String url, Class<T> responseClass) {
// JSON 응답을 받았다고 가정
String jsonResponse = "{\\"name\\":\\"jason\\", \\"age\\":29}";
Gson gson = new Gson();
// getParameterized()를 사용해서 ApiResponse<T> 타입 생성
Type responseType = TypeToken.getParameterized(responseClass).getType();
// 그리고 JSON을 파싱하여 반환
T data = gson.fromJson(jsonResponse, responseType);
ApiResponse<T> response = new ApiResponse();
response.setData(data);
response.setMessage("tired");
response.setSuccess(true);
return response;
}
문제 10: Type 객체 재사용과 성능 (난이도: ★★★)
다음 두 코드의 성능 차이를 분석하고, 최적화 방안을 제시하시오.
// 코드 A: 매번 새로 생성
public class Parser1 {
public List<String> parseStringList(String json) {
Type type = new TypeToken<List<String>>(){}.getType();
return new Gson().fromJson(json, type);
}
}
// 코드 B: 정적 필드 사용
public class Parser2 {
private static final Type STRING_LIST_TYPE =
new TypeToken<List<String>>(){}.getType();
public List<String> parseStringList(String json) {
return new Gson().fromJson(json, STRING_LIST_TYPE);
}
}
// 코드 C: getParameterized() 사용
public class Parser3 {
private static final Type STRING_LIST_TYPE =
TypeToken.getParameterized(List.class, String.class).getType();
public List<String> parseStringList(String json) {
return new Gson().fromJson(json, STRING_LIST_TYPE);
}
}
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
public class Main {
public static void main(String[] args) {
String json = "[\\"apple\\", \\"banana\\", \\"cherry\\"]";
int iterations = 1_000_000;
// 코드 A: 매번 새로 생성
Parser1 p1 = new Parser1();
long start1 = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
p1.parseStringList(json);
}
long end1 = System.currentTimeMillis();
System.out.println("Parser1 : " + (end1 - start1) + "ms");
// 코드 B: 정적 필드 사용
Parser2 p2 = new Parser2();
long start2 = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
p2.parseStringList(json);
}
long end2 = System.currentTimeMillis();
System.out.println("Parser2 : " + (end2 - start2) + "ms");
// 코드 C: 정적 필드 사용 + getParameterized() 사용
Parser3 p3 = new Parser3();
long start3 = System.currentTimeMillis();
for (int i = 0; i < iterations; i++) {
p3.parseStringList(json);
}
long end3 = System.currentTimeMillis();
System.out.println("Parser3 : " + (end3 - start3) + "ms");
}
}
// 코드 A: 매번 새로 생성
class Parser1 {
public List<String> parseStringList(String json) {
Type type = new TypeToken<List<String>>(){}.getType();
return new Gson().fromJson(json, type);
}
}
// 코드 B: 정적 필드 사용
class Parser2 {
private static final Type STRING_LIST_TYPE = new TypeToken<List<String>>(){}.getType();
public List<String> parseStringList(String json) {
return new Gson().fromJson(json, STRING_LIST_TYPE);
}
}
// 코드 C: 정적 필드 사용 + getParameterized() 사용
class Parser3 {
private static final Type STRING_LIST_TYPE = TypeToken.getParameterized(List.class, String.class).getType();
public List<String> parseStringList(String json) {
return new Gson().fromJson(json, STRING_LIST_TYPE);
}
}
Parser1 : 2559ms
Parser2 : 2093ms
Parser3 : 1946ms
어떤 방식이 가장 효율적인지 설명하고, 그 이유를 서술하시오.
B,C) Type 객체는 정적으로 재사용하는 것이 좋음 반복적으로 같은 타입을 파싱할 경우 메모리와 성능에서 이점이 있음
C) 가독성 원탑… 반드시 저거를 해야 안 헷갈릴듯
Q. 왜 3번이 빠른지 궁금하다~
문제 11: 실무 문제 해결 (난이도: ★★★)
다음과 같은 복잡한 JSON 구조를 처리해야 합니다. 적절한 TypeToken을 생성하는 코드를 작성하시오.
{
"users": {
"admins": [
{"name": "admin1", "permissions": ["read", "write", "delete"]},
{"name": "admin2", "permissions": ["read", "write"]}
],
"normal": [
{"name": "user1", "permissions": ["read"]},
{"name": "user2", "permissions": ["read"]}
]
}
}
목표 타입: Map<String, Map<String, List<User>>>
public class User {
private String name;
private List<String> permissions;
// getter, setter 생략
}
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String json = """
{
"users": {
"admins": [
{"name": "admin1", "permissions": ["read", "write", "delete"]},
{"name": "admin2", "permissions": ["read", "write"]}
],
"normal": [
{"name": "user1", "permissions": ["read"]},
{"name": "user2", "permissions": ["read"]}
]
}
}
""";
Gson gson = new Gson();
// 목표 타입: Map<String, Map<String, List<User>>>
Type type = TypeToken.getParameterized( Map.class, // Map<
String.class, // String,
TypeToken.getParameterized( Map.class, // Map<
String.class, // String,
TypeToken.getParameterized(List.class, // List<
User.class // User
).getType() // >
).getType() // >
).getType(); // >
Map<String, Map<String, List<User>>> parsed = gson.fromJson(json, type);
// 출력
Map<String, List<User>> users = parsed.get("users");
for (Map.Entry<String, List<User>> entry : users.entrySet()) {
System.out.println("[" + entry.getKey() + "]");
for (User user : entry.getValue()) {
System.out.println("- " + user.getName() + ": " + user.getPermissions());
}
}
}
public static class User {
private String name;
private List<String> permissions;
public String getName() {
return name;
}
public List<String> getPermissions() {
return permissions;
}
}
}
// 목표 타입: Map<String, Map<String, List<User>>>
Type type = TypeToken.getParameterized( Map.class, // Map<
String.class, // String,
TypeToken.getParameterized( Map.class, // Map<
String.class, // String,
TypeToken.getParameterized(List.class, // List<
User.class // User
).getType() // >
).getType() // >
).getType(); // >
이런식으로 작성하니까 덜헷갈린다~~ TypeToken.getParameterized() 작성 템플릿~~
[admins]
- admin1: [read, write, delete]
- admin2: [read, write]
[normal]
- user1: [read]
- user2: [read]
문제 12: 제네릭 메서드와 TypeToken (난이도: ★★★)
다음 제네릭 유틸리티 메서드를 완성하시오. 이 메서드는 임의의 Collection 타입을 동적으로 처리할 수 있어야 합니다.
public class JsonUtils {
// 이 메서드를 완성하시오
public static <T, C extends Collection<T>> C parseCollection(
String json,
Class<C> collectionClass,
Class<T> elementClass) {
// getParameterized()를 사용해서 동적으로 타입 생성
Type type = TypeToken.getParameterized(collectionClass, elementClass).getType();
// 예: List<String>, Set<Integer>, ArrayList<User> 등
return new Gson().fromJson(json, type);
}
// 사용 예시:
// List<String> list = parseCollection(json, List.class, String.class);
// Set<Integer> set = parseCollection(json, Set.class, Integer.class);
}
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collection;
public class JsonUtils {
public static <T, C extends Collection<T>> C parseCollection(
String json,
Class<C> collectionClass,
Class<T> elementClass) {
Type type = TypeToken.getParameterized(collectionClass, elementClass).getType();
return new Gson().fromJson(json, type);
}
}
package kice4;
import java.util.*;
public class Main {
public static void main(String[] args) {
// 예시 1: List<String>
String json1 = "[\\"apple\\", \\"banana\\", \\"cherry\\"]";
List<String> list = JsonUtils.parseCollection(json1, List.class, String.class);
System.out.println("List<String>: " + list);
// 예시 2: Set<Integer>
String json2 = "[1, 2, 3, 2]";
Set<Integer> set = JsonUtils.parseCollection(json2, Set.class, Integer.class);
System.out.println("Set<Integer>: " + set);
// 예시 3: List<User>
String json3 = """
[
{"name": "Alice", "permissions": ["read", "write"]},
{"name": "Bob", "permissions": ["read"]}
]
""";
List<User> users = JsonUtils.parseCollection(json3, List.class, User.class);
System.out.println("List<User>:");
for (User u : users) {
System.out.println("- " + u.getName() + ": " + u.getPermissions());
}
}
public static class User {
private String name;
private List<String> permissions;
public String getName() {
return name;
}
public List<String> getPermissions() {
return permissions;
}
}
}
13. 추가로 Map도 공통유틸화?!
통합본(아래에 요약본 있음)
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.*;
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
// List<String>
String json1 = "[\\"apple\\", \\"banana\\", \\"cherry\\"]";
List<String> list = JsonUtils.parseCollection(json1, List.class, String.class);
System.out.println("List<String>: " + list);
// Set<Integer>
String json2 = "[1, 2, 3, 2]";
Set<Integer> set = JsonUtils.parseCollection(json2, Set.class, Integer.class);
System.out.println("Set<Integer>: " + set);
// List<User>
String json3 = """
[
{"name": "Alice", "permissions": ["read", "write"]},
{"name": "Bob", "permissions": ["read"]}
]
""";
List<User> users = JsonUtils.parseCollection(json3, List.class, User.class);
System.out.println("List<User>:");
for (User u : users) {
System.out.println("- " + u.getName() + ": " + u.getPermissions());
}
// Map<String, Map<String, List<User>>>
String json4 = """
{
"users": {
"admins": [
{"name": "admin1", "permissions": ["read", "write", "delete"]},
{"name": "admin2", "permissions": ["read", "write"]}
],
"normal": [
{"name": "user1", "permissions": ["read"]},
{"name": "user2", "permissions": ["read"]}
]
}
}
""";
Type complexType = TypeToken.getParameterized(
Map.class, // Map<
String.class, // String,
TypeToken.getParameterized(
Map.class, // Map<
String.class, // String,
TypeToken.getParameterized(List.class, User.class).getType() // List<User>
).getType() // >
).getType(); // >
Map<String, Map<String, List<User>>> complexParsed = gson.fromJson(json4, complexType);
System.out.println("\\n[users] JSON 구조:");
for (Map.Entry<String, List<User>> group : complexParsed.get("users").entrySet()) {
System.out.println("[" + group.getKey() + "]");
for (User u : group.getValue()) {
System.out.println("- " + u.getName() + ": " + u.getPermissions());
}
}
Type innerValue = TypeToken.getParameterized(List.class, User.class).getType();
Type nestedMapValue = TypeToken.getParameterized(Map.class, String.class, innerValue).getType();
Map<String, Map<String, List<User>>> result = JsonUtils.parseMap(json4, String.class, nestedMapValue);
System.out.println("\\n[users] JSON 구조 Util로 만들어봄~:");
for (Map.Entry<String, Map<String, List<User>>> outer : result.entrySet()) {
String topLevelKey = outer.getKey();
Map<String, List<User>> groupMap = outer.getValue();
System.out.println("[" + topLevelKey + "]");
for (Map.Entry<String, List<User>> group : groupMap.entrySet()) {
System.out.println(" [" + group.getKey() + "]");
for (User u : group.getValue()) {
System.out.println(" - " + u.getName() + ": " + u.getPermissions());
}
}
}
}
}
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
public class JsonUtils {
public static <T, C extends Collection<T>> C parseCollection(
String json,
Class<C> collectionClass,
Class<T> elementClass) {
Type type = TypeToken.getParameterized(collectionClass, elementClass).getType();
return new Gson().fromJson(json, type);
}
public static <K, V> Map<K, V> parseMap(String json, Class<K> keyClass, Type valueType) {
Type type = TypeToken.getParameterized(Map.class, keyClass, valueType).getType();
return new Gson().fromJson(json, type);
}
}
공통유틸화 요약본
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
public class JsonUtils {
public static <T, C extends Collection<T>> C parseCollection(
String json,
Class<C> collectionClass,
Class<T> elementClass) {
Type type = TypeToken.getParameterized(collectionClass, elementClass).getType();
return new Gson().fromJson(json, type);
}
public static <K, V> Map<K, V> parseMap(String json, Class<K> keyClass, Type valueType) {
Type type = TypeToken.getParameterized(Map.class, keyClass, valueType).getType();
return new Gson().fromJson(json, type);
}
}
package kice4;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.*;
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
// Map<String, Map<String, List<User>>>
String json4 = """
{
"users": {
"admins": [
{"name": "admin1", "permissions": ["read", "write", "delete"]},
{"name": "admin2", "permissions": ["read", "write"]}
],
"normal": [
{"name": "user1", "permissions": ["read"]},
{"name": "user2", "permissions": ["read"]}
]
}
}
""";
// 1. 곧이곧대로 다 씀
Type complexType = TypeToken.getParameterized(Map.class, // Map<
String.class, // String,
TypeToken.getParameterized(Map.class, // Map<
String.class, // String,
TypeToken.getParameterized(List.class, User.class).getType() // List<User>
).getType() // >
).getType(); // >
Map<String, Map<String, List<User>>> complexParsed = gson.fromJson(json4, complexType);
// 곧이곧대로 출력~
System.out.println("\\n[users] JSON 구조:");
for (Map.Entry<String, List<User>> group : complexParsed.get("users").entrySet()) {
System.out.println("[" + group.getKey() + "]");
for (User u : group.getValue()) {
System.out.println("- " + u.getName() + ": " + u.getPermissions());
}
}
// 2. Map 매핑도 유틸화해봄, 2중 Map이라 두번 해야함
Type innerValue = TypeToken.getParameterized(List.class, User.class).getType();
Type nestedMapValue = TypeToken.getParameterized(Map.class, String.class, innerValue).getType();
Map<String, Map<String, List<User>>> result = JsonUtils.parseMap(json4, String.class, nestedMapValue);
// 유틸화 출력
System.out.println("\\n[users] JSON 구조 Util로 만들어봄~:");
for (Map.Entry<String, Map<String, List<User>>> outer : result.entrySet()) {
String topLevelKey = outer.getKey();
Map<String, List<User>> groupMap = outer.getValue();
System.out.println("[" + topLevelKey + "]");
for (Map.Entry<String, List<User>> group : groupMap.entrySet()) {
System.out.println(" [" + group.getKey() + "]");
for (User u : group.getValue()) {
System.out.println(" - " + u.getName() + ": " + u.getPermissions());
}
}
}
// 3. 굳이 유틸화를 해야하는가... 끊어서 쓰는 아이디어는 좋은거같음
// 1단계: List<User>
Type listOfUser = TypeToken.getParameterized(List.class, User.class).getType();
// 2단계: Map<String, List<User>>
Type innerMap = TypeToken.getParameterized(Map.class, String.class, listOfUser).getType();
// 3단계: Map<String, Map<String, List<User>>>
Type outerMap = TypeToken.getParameterized(Map.class, String.class, innerMap).getType();
// 파싱
Map<String, Map<String, List<User>>> result2 = new Gson().fromJson(json4, outerMap);
// 끊어서 쓰는 것 출력
System.out.println("\\n[users] JSON 구조 그냥 끊어서 써봄~:");
for (Map.Entry<String, Map<String, List<User>>> outer : result2.entrySet()) {
String topLevelKey = outer.getKey();
Map<String, List<User>> groupMap = outer.getValue();
System.out.println("[" + topLevelKey + "]");
for (Map.Entry<String, List<User>> group : groupMap.entrySet()) {
System.out.println(" [" + group.getKey() + "]");
for (User u : group.getValue()) {
System.out.println(" - " + u.getName() + ": " + u.getPermissions());
}
}
}
}
}
[users] JSON 구조:
[admins]
- admin1: [read, write, delete]
- admin2: [read, write]
[normal]
- user1: [read]
- user2: [read]
[users] JSON 구조 Util로 만들어봄~:
[users]
[admins]
- admin1: [read, write, delete]
- admin2: [read, write]
[normal]
- user1: [read]
- user2: [read]
[users] JSON 구조 그냥 끊어서 써봄~:
[users]
[admins]
- admin1: [read, write, delete]
- admin2: [read, write]
[normal]
- user1: [read]
- user2: [read]
'TIL(CS)' 카테고리의 다른 글
이미지 처리 (0) | 2025.09.03 |
---|---|
궁극의 제티서버 (0) | 2025.09.03 |
웹소켓이란? (feat.Spring,STOMP,SockJS) (1) | 2024.10.26 |
OOP의 SOLID 원칙 (2) | 2024.05.28 |
RDBMS의 ACID 트랜잭션과 NoSQL의 BASE 속성 (0) | 2024.05.28 |