2023. 3. 11. 22:10ใ๐พBackEnd/๐ฑ Spring
๊ธฐ๋ณธ์ ์ธ ์ฝ๋๋ฅผ ํ ์คํธ ํ๋ฉด์ JSON์ ํ์ฑํ๋ JackSon ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋๋ฌด ๋ชจ๋ฅด๊ณ ์ฌ์ฉ์ ํ์๋ค.
๊ทธ๋์ ๊ฐ๋จํ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑ์ ํด๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ์ผ๋จ ๋ฐ์ํ ์ค๋ฅ๋ฅผ ์ค๋ช ํ๊ณ Jackson์ด ์ด๋ป๊ฒ ํ์ฑ์ ํ๊ณ ๊ทธ ์ดํ์ ์ด๋ค ํ๋์ ํ๋์ง ์์๋ณด๊ฒ ๋ค.
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public UserData create(@RequestBody UserData userData){
User user = userService.registerUser(userData);
return UserData.builder()
.email(user.getEmail())
.build();
}
@Getter
@Builder
@AllArgsConstructor
public class UserData {
private Long id;
private String email;
private String name;
}
@Test
@DisplayName("register")
public void registerUserWithValidAttributes() throws Exception{
//given
given(userService.registerUser(any(UserData.class))).will(invocation -> {
UserData userData = invocation.getArgument(0);
User user = User.builder()
.email(userData.getEmail())
.build();
return user;
});
//when
//{"email":"test@exampel.com", "password":"1234",...}
mockMvc.perform(post("/users")
.contentType(APPLICATION_JSON)
.content("{\"email\": \"test@example.com\", \"name\":\"tester\"," +
"\"password\": \"test\"}"))
.andExpect(status().isCreated())
.andExpect(content().string(
containsString("\"email\":\"test@example.com\"")
));
//Then
verify(userService).registerUser(any(UserData.class));
}
์์ ์ฝ๋๋ ๊ฐ๋จํ๊ฒ ์์ฑ ํ ์คํธ๋ฅผ ํ์ธํ๋ ํ ์คํธ ์ฝ๋์ด๋ค.
UserData๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ UserData ํ์ ์ผ๋ก ๋ฐํ์ ํด์ฃผ๋ ์ฝ๋์ด๋ค.
ํ ์คํธ ์ฝ๋์ ๋ํด์ ์ค๋ช ํ๋ฉด content๋ก JSON์ ๋๊ฒจ์ Jackson์ ํตํ์ฌ ์ง๋ ฌํ๋ฅผ ํ๊ณ ์ดํ andExcept์ content๋ฅผ ํตํ์ฌ ์ญ์ง๋ ฌํ๋ฅผ ํ์ฌ ๊ฒ์ฆํ๋ ์ฝ๋์ด๋ค.
๋ด ์๊ฐ์ผ๋ก๋ ๋ฌธ์ ๊ฐ ์๋ค๊ณ ์๊ฐ์ ํ์์ผ๋ ์ค๋ฅ๊ฐ ํ๋ ๋ฐ์ํ๋๋ฐ
org.springframework.web.util.NestedServletException: Request processing failed;
nested exception is org.springframework.http.converter.HttpMessageConversionException:
Type definition error: [simple type, class com.codesoom.assignment.dto.UserData];
nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `com.codesoom.assignment.dto.UserData`
(no Creators, like default constructor, exist): cannot deserialize from Object value
(no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 1, column: 2]
์ด๋ฌํ ์ค๋ฅ๊ฐ ๋ฐ์์ ํ์๋ค. ์ค๋ฅ์ ๋ํด์ ์ดํด๋ณด๋ฉด UserData๋ฅผ ์ญ์ง๋ ฌํ ํ๋ ๊ณผ์ ์์ ์๊ธด ๋ฌธ์ ์ด๋ค.
Cannot construct instance of `com.codesoom.assignment.dto.UserData` (no Creators, like default constructor, exist)
๊ทธ ์ด์ ๋ฅผ ์ฐพ์๋ณด๋ฉด Jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ UserData ํด๋์ค์ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ํธ์ถํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ค๊ณ ํ์ง๋ง ์ง๊ธ ํด๋์ค์๋ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ญ์ง๋ ฌํ๊ฐ ์คํจํ๋ค๋ ์๋ฏธ์ด๋ค.
๊ทธ๋์ UserData์ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ถ๊ฐํ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ค.
์ด์ Jackson์ ๋ํด์ ์์๋ณด์
Jackson๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ JSON ๋ฐ์ดํฐ๋ฅผ ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํํ๋ ์ญ์ง๋ ฌํ ๊ณผ์ ์ ๋ํด์ ๋ค์๊ณผ ๊ฐ์ด ์คํ๋๋ค.
1 .JSON ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
2. JSON ๋ฐ์ดํฐ๋ฅผ ์๋ฐ ๊ฐ์ฒด๋ก ๋ณํํ๊ธฐ ์ํด Jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ๋ ObjectMapper๋ฅผ ์ฌ์ฉํฉ๋๋ค.
3. ObjectMapper๋ JSON ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด๋ค์ฌ ๊ฐ์ฒด๋ก ๋ณํํ๋๋ฐ, ์ด๋ ํด๋์ค์ ์ ๋ณด๋ฅผ ์ฐธ์กฐํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
4. ํด๋์ค์ ๋งค๊ฐ๋ณ์๊ฐ ์๋ ๊ธฐ๋ณธ ์์ฑ์๊ฐ ์๋ ๊ฒฝ์ฐ, Jackson์ ์ด ์์ฑ์๋ฅผ ํธ์ถํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
5. ์์ฑ์๊ฐ ์๋ ๊ฒฝ์ฐ, Jackson์ ๋ค๋ฅธ ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ์์ฑ์์ ๋งค๊ฐ๋ณ์์ JSON ๋ฐ์ดํฐ์ ํค๊ฐ ์ผ์นํ๋์ง ํ์ธํ๊ณ , ์ผ์นํ๋ ๊ฒฝ์ฐ ํด๋น ๊ฐ์ ๋งค๊ฐ๋ณ์์ ์ ๋ฌํ์ฌ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
6. ํด๋์ค์ ๋งค๊ฐ๋ณ์๊ฐ ์๋ ๊ธฐ๋ณธ ์์ฑ์๋ ์๊ณ , ๋ค๋ฅธ ์์ฑ์๋ ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ, Jackson์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
'๐พBackEnd > ๐ฑ Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[ Object Mapper] Dozer์ ๋ํด์ ๋ค์ด๋ ๋ดค๋? (0) | 2023.03.14 |
---|---|
[ RFC ] ๊ณต์ ๋ฌธ์๋ฅผ ํตํ์ฌ Delete์ Status๋ฅผ ์์๋ณด์ (0) | 2023.03.12 |
Spring Boot Test H2 In Memory ์ค์ ํ๊ธฐ (0) | 2023.02.28 |
[SpringBoot] Slack์ผ๋ก ์๋ฆผ ๋ณด๋ด๊ธฐ (0) | 2023.02.15 |
JPA ์์์ฑ ์ปจํ ์คํธ (0) | 2023.02.04 |