2024.03.15 - [Spring Boot] - [Spring Boot] JSON 객체 송수신 예제
위의 게시물과 내용이 이어짐
1. JsonString 를 Object 로, Object 를 JsonString 으로 변환 방법
- Json 형태로 입력받은 String을 Object로 변환
- 입력받은 Objcet 를 Json 형태의 String으로 변환
- JSONParser, Gson, object-mapper 의 3가지 방법으로 변환함
2. JSONParser 를 이용한 JsonString <-> Object 변환
- JSONObject 내부적으로 데이터 저장 시 HashMap 등의 자료구조를 사용함
2-1. build.gradle (라이브러리 추가)
dependencies {
//JSONParser
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
}
2-2. JsonString -> Object 변환
@RestController
@RequestMapping("/json-parser")
public class JsonParserController {
@PostMapping("/string-to-student")
public StudentDto stringToStudent(@RequestBody String inputString) throws ParseException {
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(inputString);
// Student 객체 생성
Student student = new Student(jsonObject.get("name").toString(),
jsonObject.get("password").toString(),
Integer.valueOf(jsonObject.get("age").toString()),
(ArrayList<String>) jsonObject.get("classes"));
// Student 객체를 StudentDTO로 변환
StudentDto studentDto = new StudentDto(student);
return studentDto;
}
}
- 실행 결과
2-3. Object -> JsonString 변환
@PostMapping("/student-to-string")
public String studentToString(@RequestBody Student student) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", student.getName());
// 비밀번호는 담지 않는다고 가정
// jsonObject.put("password", student.getPassword());
jsonObject.put("age", student.getAge());
jsonObject.put("classes", student.getClasses());
return jsonObject.toJSONString();
}
- 실행 결과
3. Gson 을 이용한 JsonString <-> Object 변환
- JSON 스펙 자체에서 데이터의 순서를 보장하지 않음
- JSONParser 를 사용하면 위의 결과처럼 데이터의 순서 보장 x
- 데이터의 순서를 보장하고 싶다면 Gson을 사용하는 것도 좋은 방법임
- Gson 라이브러리의 JsonObject 는 내부적으로 LinkedTreeMap 의 자료구조를 사용함
- 추가한 데이터의 순서대로 데이터가 저장됨
3-1. build.gradle (라이브러리 추가)
dependencies {
// Gson
implementation 'com.google.code.gson:gson:2.8.6'
}
3-2. JsonString -> Object 변환
@RestController
@RequestMapping("/gson")
public class GsonController {
@PostMapping("/string-to-student")
public StudentDto stringToStudent(@RequestBody String inputString) {
Gson gson = new Gson();
Student student = gson.fromJson(inputString, Student.class);
// Student 를 StudentDTO로 변환해서 리턴
return new StudentDto(student);
}
}
- 실행 결과
3-3. Object -> JsonString 변환
@PostMapping("/student-to-string")
public String studentToString(@RequestBody Student student) {
Gson gson = new Gson();
String jsonString = gson.toJson(student);
return jsonString;
}
- 실행 결과
- gson.toString 을 통해서 JsonString으로 변환
- 여기서 password가 그대로 노출!
3-4. Object -> JsonString 변환 + 제외 필드 추가 (password 제외)
3-4-1. @Expose 사용
- Student 클래스에 JsonString으로 변환하고 싶은 (노출하고 싶은) 필드에 @Expose 어노테이션 추가함
@Getter
@Setter
@AllArgsConstructor
public class Student {
@Expose
public String name;
public String password;
@Expose
public int age;
@Expose
public ArrayList<String> classes = new ArrayList<>();
public Student() {
}
}
- RestController 수정
@PostMapping("/student-to-string-expose")
public String studentToString2(@RequestBody Student student) {
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String jsonString = gson.toJson(student);
return jsonString;
}
- 실행 결과
- password 가 제외됨을 확인!
3-4-2. Gson의 ExclusionStrategy 사용
- ExclusionStrategy 인터페이스 구현
static class PasswordExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
// password 필드를 스킵함
return f.getName().equals("password");
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
// 스킵할 클래스는 없으므로 false 리턴
return false;
}
}
- RestController 수정
@PostMapping("/student-to-string-exclusion-strategy")
public String studentToString3(@RequestBody Student student) {
Gson gson = new GsonBuilder()
.setExclusionStrategies(new PasswordExclusionStrategy())
.create();
String jsonString = gson.toJson(student);
return jsonString;
}
- 실행 결과
- password가 제외됨을 확인!
- 제외 전략 (Exclusion Strategy) 에 해당하는 클래스를 새로 만듦으로써 다른 클래스(ex. Student) 혹은 엔티티 등을 수정하지 않고 해당 api 스펙에 맞게끔 제외 필드를 설정할 수 있음!
4. object-mapper 를 이용한 JsonString <-> Object 변환
4-1. JsonString -> Object 변환
@RestController
@RequestMapping("/object-mapper")
public class ObjectMapperController {
@PostMapping("/string-to-student")
public StudentDto stringToStudent(@RequestBody String inputString) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.readValue(inputString, new TypeReference<>() {});
Student student = new Student(map.get("name").toString(),
map.get("password").toString(),
Integer.valueOf(map.get("age").toString()),
(ArrayList<String>) map.get("classes"));
return new StudentDto(student);
}
}
- 실행 결과
4-2. Object -> JsonString 변환
@PostMapping("/student-to-string")
public String studentToString(@RequestBody Student student) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(student);
return result;
}
- 실행 결과
- objectMapper.writeValueAsString(student) 로 바로 JsonString으로 변환
- password가 그대로 노출!
4-3. Object -> JsonString 변환 + 제외 필드 추가 (password 제외)
4-3-1. @JsonIgnore 사용
- Student 클래스에서 제외하고 싶은 필드에 @JsonIgnore 어노테이션 추가
@Getter
@Setter
@AllArgsConstructor
public class Student {
public String name;
@JsonIgnore // password 필드 제외
public String password;
public int age;
public ArrayList<String> classes = new ArrayList<>();
public Student() {
}
}
- 실행 결과
- password가 제외됨을 확인!
4-3-2. ObjectMapper 커스터마이징
- Student 클래스를 수정할 수 없는 상황일 때 특정 필드 제외 가능
- 엔티티 등을 api 스펙에 맞춰서 수정하지 않고 특정 필드를 제외할 수 있기 때문에 가용성이 좋음
- Student 클래스에 @JsonFilter 어노테이션 추가
@Getter
@Setter
@AllArgsConstructor
@JsonFilter("studentFilter") // studentFilter 적용
public class Student {
public String name;
// @JsonIgnore
public String password;
public int age;
public ArrayList<String> classes = new ArrayList<>();
public Student() {
}
}
- RestController 수정
@PostMapping("/student-to-string-filter")
public String studentToString2(@RequestBody Student student) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
// studentFilter : password 필드 제외 한 모든 필드를 직렬화
SimpleFilterProvider filter = new SimpleFilterProvider().addFilter("studentFilter",
SimpleBeanPropertyFilter.serializeAllExcept("password"));
objectMapper.setFilterProvider(filter);
String result = objectMapper.writeValueAsString(student);
return result;
}
- 실행 결과
- password 가 제외됨을 확인!
'Spring Boot' 카테고리의 다른 글
[AWS] EC2 서버 시간 설정 (TimeZone 변경) (0) | 2024.03.26 |
---|---|
[Spring Boot] 원하는 시간에 특정 코드 자동 실행시키기 (@Scheduled) (0) | 2024.03.26 |
[Spring Boot] JSON 객체 송수신 예제 (0) | 2024.03.15 |
[Spring Boot] JaCoCo로 테스트 커버리지 확인 (3) | 2024.01.30 |
[Spring Boot] 로그인 기능 구현 (8) - 페이스북 로그인 (OAuth 2.0) (0) | 2024.01.14 |