multipart/form-data to java object

Flexjson을 사용하면서 테스트를 매번 content-type이 application/json 인 string body로만 보내다 보니 파일과 폼값 전송을 위해 multipart/form-data 사용을 하면서 헷갈리게 됐다.

기존의 방법과 동일하게 JSONDeserializer를 이용하면 알아서 object에 매핑이 될 줄 알았는데 그게 안된다. 요상한 캐스팅 예외를 발생시키니 이걸 처리해야 한다.

[error] play - Cannot invoke the action, eventually got an error: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
[error] application - 

! @6g7en65m3 - Internal server error, for (POST) [/items?access_token=1234_1] ->

play.api.Application$$anon$1: Execution exception[[ClassCastException: java.lang.String cannot be cast to java.util.Map]]
 at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.0]
 at play.api.DefaultApplication.handleError(Application.scala:399) ~[play_2.10.jar:2.2.0]
 at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) ~[play_2.10.jar:2.2.0]
 at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) ~[play_2.10.jar:2.2.0]
 at scala.Option.map(Option.scala:145) ~[scala-library.jar:na]
 at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) ~[play_2.10.jar:2.2.0]
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
 at flexjson.factories.BeanObjectFactory.instantiate(BeanObjectFactory.java:17) ~[flexjson-3.1.jar:na]
 at flexjson.ObjectBinder.bind(ObjectBinder.java:95) ~[flexjson-3.1.jar:na]
 at flexjson.JSONDeserializer.deserialize(JSONDeserializer.java:184) ~[flexjson-3.1.jar:na]
 at com.unionpool.dottegi.api.controllers.ItemController.addItem(ItemController.java:37) ~[na:na]
 at Routes$$anonfun$routes$1$$anonfun$applyOrElse$8$$anonfun$apply$22.apply(routes_routing.scala:129) ~[na:na]
 at Routes$$anonfun$routes$1$$anonfun$applyOrElse$8$$anonfun$apply$22.apply(routes_routing.scala:129) ~[na:na]

그럼 기존과 다른 것은 뭔가. 기존에는 request의 json에서 body를 따오는데 JsonNode의 asJson() 메소드를 이용하여 말 그대로 json 형태로 받아온다. 그러니 당연히 JSONDeserializer로 deserialization이 가능했던 것.

JsonNode userJson = request().body().asJson();
User user = new JSONDeserializer()
 .deserialize(userJson.toString(), User.class);

이번에는 content-type이 multipart/form-data. 좀 다른 방식으로 뽑아온다.

MultipartFormData body = request().body().asMultipartFormData();
...
ItemMain item = new JSONDeserializer()
 .deserialize(body.toString(), ItemMain.class);

위처럼 그대로 하면 에러가 난다는 얘기. 대충 뭐가 문제인지는 알았으니 이제 해결한다.
...
MultipartFormData를 Json이나 String 형태로 캐스팅하면 뭔가 될 줄 알았지만 미묘하게 안된다. 되는 방법도 있겠지만 일단 급한대로 body를 Map 형태로 리턴해 주는 asFormUrlEncoded() 메소드를 이용해 하나 하나 가져와서 새 java object를 만들어 준다.

 Map bodyMap = body.asFormUrlEncoded();

 ItemMain item = new ItemMain();
 item.setUser_id(user_id);
 item.setPrice_standard(Integer.valueOf(bodyMap.get("price_standard")[0]));
 item.setTransaction_flag(bodyMap.get("transaction_flag")[0].charAt(0));
 item.setShip_rate_standard(Integer.valueOf(bodyMap.get("ship_rate_standard")[0]));
 item.setStory(bodyMap.get("story")[0]);

일단 이렇게 해서 해결... 하지만 좀 더 심플한 방법이 있는지 나중에 찾아보도록 하겠다.

댓글 없음:

댓글 쓰기