Wookim

Spring 복잡한 json 데이터 받기 본문

카테고리 없음

Spring 복잡한 json 데이터 받기

개발자인 경우 2020. 1. 6. 19:01

프론트에서 데이터를 가공하여 서버로 데이터를 보낼 때, 

문제를 겪었다.

자바스크립트에서는 데이터를 자유자재로 다루다가,

막상 서버에서 데이터를 다루려 하니 막막해진것...

 

프론트에서 단순한 { } 객체를 보낼 때는 서버에서 단순히 Map으로 받으면 

알아서 파싱을 잘 해주지만 (설정이 되어있다는 전제하에)

 

{ a: b,

  b : [ 1, 2, [3, 4] ]

  c : { e: 2, f: 5}

}  

이런 식의 데이터를 받고나서 사용할 때 문제가 된다.

 

위 상황에서

@RequestBody Map<String, Object> params 이런식으로 

파라미터를 받을 수 있지만,

막상 꺼내 쓸려면 캐스팅 하는데 머리를 굴려야 한다.

 

아래 예제를 보자.

 

javascript 

프론트의 데이터는 아래와 같다.

// 데이터 형식
var dataMap = {
id : ["a", "b"],
pw : ["c", "d"]
}
// data json 문자열 화
var jsonString = JSON.stringify(dataMap);

// server에 요청
$ajax({
    url : 'url',
    contentType: 'application/json', // 보내는 데이터 json 일때 필수 옵션
    method : 'POST', // 전달방식이 controller와 일치해야함
    jsonData : jsonString, // 전달하는 데이터
    ...
})    

※ 주의점

  • ajax 파라미터 중 contentType: 'application/json' 값은 꼭 보내야 한다. 서버에 데이터를 json으로 보내겠다는 뜻
  • ajax 파라미터 중 jsonData에 보낼 데이터를 매핑하는데 이때, 반드시 데이터를 JSON.stringify()메소드를 이용해 데이터를 json 문자열화 해서 보내야 한다. 서버에 json으로 데이터 보낸다고 했는데 다른 형식으로 보내면 문제가 생기는 이치.
 

 

java의 controller class

// 클라이언트에 url 매핑이 되어야 하고
 @RequestMapping(value = "/url", method = RequestMethod.POST, produces = "application/json; charset=utf8")
    public @ResponseBody HashMap <String, Object> method(@RequestBody Map<String, Object> param){

// 구글의 json paser 라이브러리
   Gson gson = new Gson();

 // jsonPaserPser 클래스 객체를 만들고 해당 객체에 
   JsonParser jparser = new JsonParser();

// param의 id 오브젝트 -> 문자열 파싱 -> jsonElement 파싱
   JsonElement elementId = jparser.parser(param.get("id").toString());
    JsonElement elementPw = jparser.parser(param.get("pw").toString()); 

// JsonElement -> List<String>으로 파싱
   List <String> idList = gson.fromJson(elementId, (new TypeToken<List<String>>() {  }).getType());
   List <String> pwList = gson.fromJson(elementId, (new TypeToken<List<String>>() {  }).getType());
}

※ 주의점

  • @ReqeustMappling 어노테이션 파라미터에 produces = "application/json; charset=urf8" 를 추가해야 한다. 데이터를 utf8의 json으로 받겠다는 뜻. 
  • 컨트롤러의 파라미터앞에 @RequestBody 어노테이션을 넣어야 한다. 프론트에서 전달 한 json 데이터를 해당 파라미터에 매핑시킨다는 뜻. 

필자는 json을 POJO(plain old java object)로 변환하기 위해 구글의 gson 라이브러리를 사용했다.

 

 

 


 // jsonPaserPser 클래스 객체를 만들고 해당 객체에 
   JsonParser jparser = new JsonParser();

// param의 id 오브젝트 -> 문자열 파싱 -> jsonElement 파싱
   JsonElement elementId = jparser.parser(param.get("id").toString());
   JsonElement elementPw = jparser.parser(param.get("pw").toString()); 
}

JsonPaser 클래스를 사용해 JsonElement 객체를 생성한다.

프로세스는 다음과 같다.

  1. 프론트 json data -> 서버 @RequestBody param 파라미터로 매핑 (Map이든 List든 가능한 것으로 알고있다.)
  2.  param에 매핑된 데이터를 문자열로 변환한다. 위 코드의 param.get("id").toString() 부분
  3. 변환한 값을 JsonParser 객체의 parser()메소드에 파라미터로 전달한다.
  4. 해당 메소드의 리턴값은 JsonElement 객체이다.

반환 받은 JsonElement를 이용해 원하는 POJO. 즉 원하는 자바 객체 타입으로 변환하는 것이다.


// JsonElement -> List<String>으로 파싱
   List <String> idList = gson.fromJson(elementId, (new TypeToken<List<String>>() {  }).getType());
   List <String> pwList = gson.fromJson(elementId, (new TypeToken<List<String>>() {  }).getType());
}

Gson 클래스의 사용 프로세는 다음과 같다.

 

  1. Gson 클래스 인스턴스 생성
  2. Gson의 인스턴스를 이용해 JsonElement 객체를 POJO로 캐스팅
 

Gson은 java의 JsonElement를 POJO로 변환하는 작업을 한다.

이때, Gson 클래스의 fromJson() 메소드를 사용하며 해당 메소드는 다음과 같은 파라미터를 필요로 한다.

(해당 메소드는 오버로딩이 되어있으니 참고할 것. 아래 코드는 Gson document 내용이다.)

public <T> T fromJson​(JsonElement json, java.lang.Class<T> classOfT) throws JsonSyntaxException

json 파라미터에 Json 객체를 입력하면된다. 두번째 인자는 변환 할 POJO 객체 타입이다.

(참고 JsonElemnt는 JsonObject의 상위 클래스)

 

gson.fromJson(elementId, (new TypeToken<List<String>>() {  }).getType());

gson.fromJson(elementId, (new TypeToken<List<String>() {  }).getType() );

 

위 코드중 붉은색으로 표시된 값이 변환하려는 POJO의 타입이다.

다양한 객체 타입을 지정할 수 있고 이 글의 핵심부분이다.

 

해당 파라미터는 POJO의 타입을 입력해야 한다.

이를 위해 TypeToken 클래스의 getType()메소드를 이용해 입력한 객체의 타입을 반환한다.

 

Comments