์ด ๊ธ์ ์ด ๋ฐฐ๊ฒฝโฆ
ํด๋ผ์ด์ธํธ์์ HTTP Body์ Json์ ์ค์ด ์์ฒญ์ ์ค์ด ๋ณด๋ด๊ณ ์ด๋ฅผ ๋ฐ๋ DTO๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ๊ณ ์์๋ค.
ํ์ง๋ง API ๋ช
์ธ๋ก ํด๋ผ์ด์ธํธ์์๋ key ๋ค์ด๋ฐ์ผ๋ก ์ค๋ค์ดํฌ ์ผ์ด์ค๋ฅผ ์ฌ์ฉํ๊ณ ,
DTO ํ๋๋ก๋ ์ค๋ค์ดํฌ ์ผ์ด์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ Jackson์ด DTO์ ์ ๋๋ก ๋งคํํ์ง ๋ชปํด ์์ธ๊ฐ ๋ฐ์ํ๋ค.
๊ทธ๋์ API ๋ช
์ธ์์, ํด๋ผ์ด์ธํธ๊ฐ key๋ฅผ ์ค๋ค์ดํฌ ์ผ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด๋ด์ฃผ๋๋ก ๋ฐ๊พธ๋ ค ํ์์ผ๋,
๋๋ํ ์คํ๋ง์ ์ด๋ฅผ ์ํ ์ด๋
ธํ
์ด์
์ ์ ๊ณตํด์ฃผ๊ณ ์์๋ค.
๋ฌธ์ ์ํฉ ํ ์คํธ
TestDto
public class TestDto {
private Long testId;
public TestDto() {
}
public TestDto(Long testId) {
this.testId = testId;
}
public Long getTestId() {
return testId;
}
public void setTestId(Long testId) {
this.testId = testId;
}
}
- ํ๋๊ฐ ์ค๋ค์ดํฌ ์ผ์ด์ค
Test2Dto
public class Test2Dto {
private Long test_id;
public Test2Dto() {
}
public Test2Dto(Long test_id) {
this.test_id = test_id;
}
public Long getTest_id() {
return test_id;
}
public void setTest_id(Long test_id) {
this.test_id = test_id;
}
}
- ํ๋๊ฐ ์นด๋ฉ ์ผ์ด์ค
TestController
@RestController
public class TestController {
@GetMapping("/test")
public ResponseEntity<TestDto> test() {
return ResponseEntity.ok().body(new TestDto(10L));
}
@PostMapping("/test")
public ResponseEntity<TestDto> test(@RequestBody TestDto testDto) {
System.out.println(testDto.getTestId());
return ResponseEntity.ok().body(new TestDto(10L));
}
@GetMapping("/test2")
public ResponseEntity<Test2Dto> test2() {
return ResponseEntity.ok().body(new Test2Dto(10L));
}
@PostMapping("/test2")
public ResponseEntity<Test2Dto> test2(@RequestBody Test2Dto testDto) {
System.out.println(testDto.getTest_id());
return ResponseEntity.ok().body(new Test2Dto(10L));
}
}
์ด ๋ ๋ค์๊ณผ ๊ฐ์ ํ ์คํธ๋ฅผ ๋๋ ค๋ณธ๋ค.
@Test
void postTest() throws Exception {
// given
Test2Dto testDto = new Test2Dto(10L);
String json = new ObjectMapper().writeValueAsString(testDto);
System.out.println(json);
// then
mockMvc.perform(MockMvcRequestBuilders
.post("/test")
.content(json)
.header("Content-Type", "application/json"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.test_id").value(10L));
}
๊ฒฐ๊ณผ๋ ์คํจํ๋ค!
์๋ํ๋ฉด ํด๋ผ์ด์ธํธ๋ ์ค๋ค์ดํฌ ์ผ์ด์ค๋ก ํค ๊ฐ์ ๋ณด๋ด๊ณ ์๋ต์ ๋ํ ํค ๊ฐ๋ ์ค๋ค์ดํฌ ํ๊ธฐ๋ฒ์ด์๋๋ฐ,
๋ฐํํ๋ DTO์ ํ๋๊ฐ ์นด๋ฉ ์ผ์ด์ค์ด๊ธฐ ๋๋ฌธ์ ์๋์ผ๋ก ํค ๊ฐ์ด ์นด๋ฉ ์ผ์ด์ค๋ก ์กํ๊ธฐ ๋๋ฌธ์ด๋ค.
ํ๋ก ํธ์์๋ ์ค๋ค์ดํฌ ์ผ์ด์ค๊ฐ ์ปจ๋ฒค์
์ด๊ณ , ์ฐ๋ฆฌ ์๋ฐ์์๋ ์นด๋ฉ ์ผ์ด์ค๊ฐ ์ปจ๋ฒค์
์ธ๋ฐโฆ
๊ทธ๋ผ DTO์ ํ๋๋ฅผ ์ค๋ค์ดํฌ๋ก ๋ฐ๊ฟ์ผ ํ๋? ํน์ ์์ฒญ์ ํค ๊ฐ์ ์นด๋ฉ๋ก ๋ฐ๊ฟ์ผ ํ๋? ๐คทโโ๏ธ
@JsonProperty
๋ง๋ฅ ์คํ๋ง์ ์ญ์ ์ด์ ๋ํ ์ด๋
ธํ
์ด์
์ ์ ๊ณตํด์ค๋ค.
@JsonProperty
๋ JSON ๋ณํ ์ key ์ด๋ฆ์ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋๋ก ์ค์ ํ ์ ์๊ฒ ํด์ค๋ค.
์ด ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ jackson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํ์ง๋ง, ์ด๋ฏธ ์คํ๋ง ๋ด๋ถ์์๋ jackson์ ์ฌ์ฉํ๊ณ ์๋ค.
์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ํ๋ ํ๋์ ํด๋น ์ด๋ ธํ ์ด์ ์ ๋ฌ๊ณ , ๋งคํํ key ์ด๋ฆ์ ์ต์ ์ผ๋ก ์ค๋ค.
public class TestDto {
@JsonProperty("test_id")
private Long testId;
public TestDto() {
}
public TestDto(Long testId) {
this.testId = testId;
}
public Long getTestId() {
return testId;
}
public void setTestId(Long testId) {
this.testId = testId;
}
}
์ด๋ ๊ฒ ๋๋ฉด ํ ์คํธ ์ฑ๊ณต์ด๋ค!
๊ทธ๋ฌ๋ฉด ํ๋ ํ๋ํ๋์ ์ด๋ ๊ฒ ๋งคํํด์ฃผ์ด์ผํ๋โฆ?
@JsonNaming
๋คํํ๋ ์ด๋ฐ ์ค๋ณต๋๋ ์์
์ ์คํ๋ง ์ด๋
ธํ
์ด์
์ผ๋ก ํด๊ฒฐํ ์ ์๋ค.
ํด๋์ค์ @JsonNaming
์ ๋ถ์ด๋ฉด ๋ชจ๋ ํ๋์ ๋ํ ํ๊ธฐ๋ฒ ๋งคํ์ ์ ํ ์ ์๋ค.
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
public class TestDto {
private Long testId;
public TestDto() {
}
public TestDto(Long testId) {
this.testId = testId;
}
public Long getTestId() {
return testId;
}
public void setTestId(Long testId) {
this.testId = testId;
}
}
์ฐธ๊ณ ๋ก ํ๊ธฐ๋ฒ ์ ๋ต์ SnakeCaseStrategy
๋ง๊ณ ๋ ๋ค์ํ๋ค!
์ ์ญ์ ์ผ๋ก ์ค์ ํ๊ณ ์ถ์ด!
application.properties ์์ ๋ค์๊ณผ ๊ฐ์ด ์ ํ๋ฆฌ์ผ์ด์
์ค์ ์ผ๋ก ๋ ์๋ ์๋ค.
์ด๋ฌ๋ฉด ๊ฐ๊ฐ์ ํด๋์ค์ ์ด๋
ธํ
์ด์
์ ๋ฌ์์ฃผ์ง ์์๋ ๋ชจ๋ ํค ๋งคํ์ ๋ํ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค!
spring.jackson.property-naming-strategy=SNAKE_CASE