가변적(key, value변수가 어떤게 들어올지 모름..)으로 넘어오는 JSON 데이터가 있으며 특징으로는
upperCase에 underscope으로 Key값이 이뤄져있다. (이건 불변)
이때 카멜케이스로 만들어놓은 VO에 setting하는 과정 or Map으로 받는 과정에서 나름(...) 고민해본 흔적을 남기고자 한다...
[ FieldNamingStrategy 를 커스텀 하자! ]
- toJson
FieldNamingStrategy을 커스텀해서 내가 작성한 규칙으로 키값이 변경된 JSON 키값으로 변경 가능
FieldNamingStrategy을 커스텀해서 내가 작성한 규칙으로 키값이 변경된 JSON 키값으로 변경 가능
- fromJson
역직렬화 시 적용이 안되는데 이유를 모르겠다..
ex. {“UP_DOWN" : “하하”} 인 경우, 맵핑하고자 하는 Class의 필드값이 upDown인 경우 맵핑이 안됨
이때는 @SerializedName 이용
@SerializedName(“UP_DOWN")
private String upDown;
단점으로는….필드값이 많아지면….하나씩 선언해줘야할..꺼같다..(끔찍)
역직렬화 시 적용이 안되는데 이유를 모르겠다..
ex. {“UP_DOWN" : “하하”} 인 경우, 맵핑하고자 하는 Class의 필드값이 upDown인 경우 맵핑이 안됨
이때는 @SerializedName 이용
@SerializedName(“UP_DOWN")
private String upDown;
단점으로는….필드값이 많아지면….하나씩 선언해줘야할..꺼같다..(끔찍)
[ 상세 코드]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
import com.google.gson.FieldNamingStrategy;
import java.lang.reflect.Field;
public class customNaming implements FieldNamingStrategy { // 커스텀 필드네이밍 전략 클래스
// 대문자 언더스콥 -> 카멜케이스로
@Override
public String translateName(Field f) {
int cnt = 0;
StringBuilder tmpStr = new StringBuilder();
String keyVal = f.getName(); // Json 데이터 키값 가져옴
String[] splitVal = keyVal.toLowerCase().split("_");
for (String str : splitVal) {
if (cnt == 0) {
tmpStr.append(str);
cnt++;
} else {
str = str.trim();
StringBuilder stringBuilder = new StringBuilder(str);
stringBuilder.setCharAt(0, Character.toUpperCase(str.charAt(0))); // 맨 앞 한글자만 대문자로
String afterStr = stringBuilder.toString();
tmpStr.append(afterStr);
}
}
return tmpStr.toString();
}
//------------------------------------------
// 호출 부분
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingStrategy(new customNaming());
Gson gson = gsonBuilder.create();
testVO testVO = gson.fromJson(str, testVO.class);
|
넘어오는 JSON데이터의 키값이 가변적인 경우
VO에 다 맵핑할 수 없다. 따라서 맵으로 받는 방식
[ 제이슨 String 데이터 -> 링크드해쉬맵(키값이 카멜 적용이된) 으로 변환 (순서성 지키기위해) ]
- 상황설명
- 뷰에서 Ajax를 이용하여 목록 클릭 시 테이블이 있는 레이어 팝업을 띄우는 상황
- 데이터는 DB에서 조회함. TH 데이터(코드값과 코드값이 의미하는 한글명)와 JSON 형식의 문자열이 저장되어있다.
- TH_CODE 값과 JSON 데이터의 키값이 다른 경우는 없다.
- 테이블에 뿌려줄때 각 항목이 일치하게 뿌려줘야 한다.
[ 테이블 Th에 뿌려줄 데이터 DB 조회 결과]
- 불특정 시기에 DB의 데이터들이 언제 UPDATE, INSERT, DELECT 될지 모르는 상황
TH_CODE
|
TH_NAME
|
UP_DOWN
|
제목
|
[ 백단으로 넘어온 JSON 데이터 DB 조회 결과]
- JSON 데이터 내의 순서는 랜덤. (어느값이 먼저올지 모름)
- 문자열로 된 json data이다.
{“USE_YES_NO” :”NO”, “UP_DOWN” : “DOWN" }
|
[ 상세 코드]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
// 테이블 컬럼은 안 바뀌는데 VO를 안쓰고 왜 굳이 Map을 쓴건지?
// - 순서성이 중요하기 때문에 DB조회 순서로 그대로 가져오기 위해 LinkedHashMap 이용
List<LinkedHashMap<String, Object>> thList = new ArrayList<LinkedHashMap<String, Object>>();
List<LinkedHashMap<String, Object>> jsonList = new ArrayList<LinkedHashMap<String, Object>>();
String keyVal = ""; // JSON 데이터가 있는 쿼리 DB조회 후 컬럼값을 담을 변수
String makeJsonStr = "{"; //json 형식으로 문자열 만들어줄 변수
String jsonKeyStr = ""; // JSON 데이터의 키값을 담을 변수
for(Map<String, Object> vo : resultList){ // resultList : 한 컬럼에 제이슨 형식의 문자열이 들어있다. 또한 ROW가 여러줄이기 때문에 List<Map> 형태로 가져온다
Iterator<String> itr = vo.keySet().iterator(); // 키 리스트 (== 컬럼 이름값들이 들어 있을 것)
while(itr.hasNext()){
keyVal = itr.next();
if (!keyVal.equals("JSON_DATA")) { // 제이슨 데이터가 들어있는 컬럼이름이 아닌 경우
continue;
}
JSONObject obj = new JSONObject(vo.get(keyVal)); // JSONOBJECT : JSON 문자열 형태를 KEY : VALUE 형태로 형 변환
Iterator<String> itr2 = obj.keys();
while(itr2.hasNext()){
jsonKeyStr = itr2.next();
makeJsonStr += "\'"+jsonKeyStr + "\' : \'" + obj.getString(jsonKeyStr) + "\',"; // 카멜케이스를 적용하려면 jsonKeyStr 대신 JdbcUtils.convertUnderscoreNameToPropertyName(jsonKeyStr) 이용
}
makeJsonStr = makeJsonStr.substring(0,makeJsonStr.lastIndexOf(","))+"}";
LinkedHashMap<String, Object> jsonVo = new Gson().fromJson(makeJsonStr, new TypeToken<LinkedHashMap<String, Object>>(){}.getType());
// th 코드값과 map으로 변환된 json 카값을 맞는 값을 맵핑하는 과정
// th 코드값기준으로 키값 비교 돌리는 중
LinkedHashMap<String, Object> finalLinkMap = new LinkedHashMap<>();
for(Map<String, Object> thMap : resultTh){ // resultTh : th의 코드와 한글 이름값을 가져온 쿼리. List<Map> 형태
Iterator<String> itr3 = thMap.keySet().iterator();
while(itr3.hasNext()){
String keyVal2 = itr3.next();
if (keyVal2.equals("TH_CODE")) { // th코드값이 들어있는 컬럼 이름인 경우
String seachKeyVal = String.valueOf(thMap.get(keyVal2)); // th코드값 할당
finalLinkMap.put(seachKeyVal, jsonVo.get(seachKeyVal)); // th코드값, th코드값에 해당하는 JSON value 값
}
}
}
jsonList.add(finalLinkMap);
makeJsonStr = "{"; // 초기화
}
}
map.put("jsonList", jsonList);
return new Gson().toJson(map);
}
|
'Spring' 카테고리의 다른 글
[JPA 공부일지] JPA와 DB설정 동작확인 (0) | 2020.01.27 |
---|---|
[스프링부트 기초] 스프링부트 활용: 외부설정,프로파일,로깅 (0) | 2019.12.02 |
[스프링 프레임워크 핵심 기술] IoC 컨테이너 (0) | 2019.12.02 |
@Component, @Service, @Repository, @Controller?? (0) | 2019.05.26 |
댓글