개발자의 오르막
Thymeleaf 에서 자바스크립트로 객체 값 전송 본문
어떤 방법을 쓰더라도 객체가 아닌 string 값은 스크립트에 모두 전송이 됐다.
그러나 컨트롤러에서 받은 객체 값을 전송하는 건 스크립트 단으로 안됐다..ㅠㅠ
객체가 아닌 string 값은 스크립트에 모두 전송이 됐다.
그러나 컨트롤러에서 받은 객체 값을 전송하는 건 스크립트 단으로 안됐다..ㅠㅠ
일반적으로 사용하는 방법이 CDATA인데,, 일단 방법을 찾아보도록 하겠다.
# CDATA
<script th:inline="javascript">
/*<![CDATA[*/
var query = [[${query}]];
console.log(message);
/*]]>*/
</script>
- 거의 주로 객체를 전달하는 방식이 CDATA이다.
# 객체 전달
var exampleDto = [[${dto}]];
console.log("exampleDto : ",exampleDto);
- 이 방법이 내가 주로 썼던 방법이다. 근데 이 방법도 아래와 같은 에러로 안먹히는 걸 보면
타임 리프의 표현이 잘못된게 아니라 다른 요인이 있다는 것이다.
# 해결답안
- 이 문제의 원인은 CDATA 에 전송한 객체의 NULL 값 처리를 안해줬기 때문에 생긴 일이었다.
스크립트에 전달할 dto 가 id에 존재여부에 따라 null 값이 될수 있고, 값을 가질 수 있었다.
그런데 id 가 없을 때는 null 값임으로 serialize 가 불가한 것이었다.
밑의 코드처럼 NULL 값 처리를 해주니까 스크립트로 데이터가 잘 넘어갔다.
@RequestMapping({"new", "edit/{id}"})
public ModelAndView resister(@PathVariable(name = "id", required = false) Long id) throws NotFoundException {
ModelAndView mav = new ModelAndView("cep/homecc/editor");
if (id != null) {
ExampleDto dto = exampleService.getExample(id);
mav.addObject("dto", dto);
}
return mav;
}
--------------------------------------------------삽질 과정입니다..-------------------------------------------------------------
# Error Message
An error happened during template parsing
위의 에러메시지는 템플릿 특정 화면을 랜더링할 때 발생했다는 것을 알려주는 메시지이다.
An exception was raised while trying to serialize object to JavaScript using Jackson
이 메시지가 원인인데, serialize object to Javascript using jackson 을 해결해야 한다.
이 오류메시지를 해결하는 방안은 크게 @JsonIgnore 이나 ObjectMapper 를 활용한다고 소개되어 있다.
아마 자바스크립트에서 JSON 형태의 데이터를 파싱할 때 오류가 나는 모양이다. ( 객체 → JSON 데이터 )
com.fasterxml.jackson.databind.JsonMappingException
Infinite recursion (StackOverflowError)
(through reference chain:
net.grovesoft.core.model.ConstructionExample["partner"]->
net.grovesoft.core.model.Partner["constructionExampleList"]->
org.hibernate.collection.internal.PersistentBag[0]->
net.grovesoft.core.model.ConstructionExample["partner"]->
net.grovesoft.core.model.Partner["constructionExampleList"]->
org.hibernate.collection.internal.PersistentBag[0]->
net.grovesoft.core.model.ConstructionExample["partner"]->
net.grovesoft.core.model.Partner["constructionExampleList"]->
org.hibernate.collection.internal.PersistentBag[0]
- 이 메시지를 보면, ConstructionExample 모델의 partner 이란 필드가
Partner 모델의 constructionExampleList 란 필드로 가게 되고,
이게 PersostentBag[0] 으로 가는데, 다시 partner 란 필드로 가게되면서 무한 루핑이 되는 상태이다.
뷰에서
내가 객체를 조회하려고 하는데,
객체의 정보를 불러올 때, Partner 를 불러오려고하고,
이 Partner 에서 constructionExample List 를 다시 불러오려고 하는데
이 ConstructionList안의 ConstructionExample 에는 또 파트너가 있는 거고,
이래서 순환참조 식으로 무한루프가 동작하게되면서
스택오버플로우 현상이 발생하면서
에러가 발생한거지
그러면 내가 양반향, 단방향을 잘못 지정해줬던가
@JsonIgnore 어노테이션을 활용하거나
@ResponseBody 라는 어노테이션을 활용해서 이 현상을 자동적으로 잡게 해주던가
ObjectMapper 를 통해 직렬화, 비직렬화를 설정해주는 방법이 있다.
근데 궁금한건
내가 cosntructionExample 에서 Partner (시공자) 가 누군지 알고 싶은거고
Partner (시공자) 를 봤을 때 시공자가 행했던 ConstructionExample 들을 List로 알고 싶은 건데,
두개의 필드가 존재해야 하지 않을까?
그러면 양방향인가?
# Jackson Library
Jackson 은 자바용 json 라이브러리이며, Json 분만 아니라 XML/YAML/CSV 등 다양한 형식의 데이타를
기술할 수 있으며, Json 의 약점 중 하나인 문서화와 데이터 validation 문제를 해결한다.
POJOs to JSON and back
POJO 기반의 자바 객체들을 JSON 형태의 데이터로 변환할 때 사용하는 라이브러리
SpringBoot 에서 기본으로 포함됨
@Bean 에 ObjectMapper 등록해놓고 싱글톤으로 주입 받아서 쓰기 때문에 성능도 우수함.
- 사용법
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
먼저 ObjectMapper 객체를 생성한다.
MyValue value = mapper.readValue(new File("data.json"), MyValue.class);
// or:
value = mapper.readValue(new URL("http://some.com/api/entry.json"), MyValue.class);
// or:
value = mapper.readValue("{\"name\":\"Bob\", \"age\":13}", MyValue.class);
사용하고자 하는 클래스의 객체를 JSON 형태로 읽고 싶을 때
ObjectMapper 클래스의 readValue 메소드에 등록한다.
mapper.writeValue(new File("result.json"), myResultObject);
// or:
byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject);
// or:
String jsonString = mapper.writeValueAsString(myResultObject);
사용하고자 하는 객체를 JSON 형태로 쓰고 싶을 때 위의 메소드를 사용한다.
package test_java;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main
{
public static void main(String[] args) throws IOException
{
ObjectMapper obm = new ObjectMapper();
/** Json문자열 -> Map */
String jsonStr = "{ \"name\" : \"민\" , \"age\" : 28 }";
Map<String, Object > map = new HashMap<String, Object>();
map = obm.readValue(jsonStr, new TypeReference<Map<String, Object>>() {});
//System.out.println("jsonString -> map : " + map);
/**Map -> Json문자열 */
Map<String ,Object> map2 = new HashMap<String, Object>();
map2.put("name", "미니미니");
map2.put("age", 100 );
String jsonStr2 = obm.writerWithDefaultPrettyPrinter().writeValueAsString(map2);
//System.out.println("map -> jsonString : " + jsonStr2);
/** json문자열 -> javaObject */
User user = obm.readValue(jsonStr, User.class);
/**javaObject -> json문자열 */
User user1 = new User();
user1.setName("식빵");
user1.setAge(3);
String user1Str = obm.writeValueAsString(user1);
//System.out.println(user1Str);
/**List<Object> -> Json문자열 */
List<User> userList = new ArrayList<User>();
User u1 = new User();
u1.setName("dodo");
u1.setAge(38);
userList.add(u1);
User u2 = new User();
u2.setName("동길");
u2.setAge(20);
userList.add(u2);
User u3 = new User();
u3.setName("통통");
u3.setAge(10);
userList.add(u3);
String userListStr = obm.writeValueAsString(userList);
System.out.println(userListStr);
/** JsonList문자열 -> List<Object> */
List<User> userList2 = obm.readValue(userListStr, new TypeReference<List<User>>(){});
}
}
에러가 발생했을 때 궁금한게, 이게 JAVA 단에서 Binding 에러가 난 게 아니라 JAVASCRIPT 에서 난거면
JSON 형태를 파싱할 때 문제가 발생한 것 아닐까
JackSon 라이브러리는 POJO 자바 객체를 JSON 형태로 파싱할 때 쓰는 ObjectMapper 이고,
근데 이거는 insert 에서 각각 input type 의 value 들을 JSON 형태의 객체로 저장 및 전달하고
그럴 POST 전송할 때 사용하는 메서드들인데..
- JSON.stringify()
- JSON.parse(객체)
- 참조사이트
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
내가 하고 싶은 건, thymeleaf 에서 받아온 객체를 JAVASCRIPT 에서 객체로 등록하고 싶은 거고,
- @JsonIgnore
JsonIgnore 은 해당 필드 위에 어노테이션의 형태로 사용되는데,
Json 형태로 데이터를 주고 받을 때 응답결과에 해당 필드를 포함하지 않겠다고 선언하는 경우에 사용된다.
- 직렬화, 비직렬화
- @ObjectMapper
# 참조 링크
- jackson - databind 깃허브 참조 링크
https://github.com/FasterXML/jackson-databind
- JAVA Json library jackson 사용법
https://www.lesstif.com/pages/viewpage.action?pageId=24445183
'Trouble Shouting' 카테고리의 다른 글
[SpringBoot] 컴파일 오류. WindowDefender 를 확인하라 (0) | 2019.11.04 |
---|---|
[Thymeleaf] th:check DB 값에 따라 체크하기 (2) | 2019.11.03 |
No default constructor for entity jpa (0) | 2019.10.30 |
IntelliJ 자바 컴파일 및 인코딩 에러 문제 (0) | 2019.10.22 |
REST 기반 GET 방식 중 NULL 값 처리 (0) | 2019.10.07 |