JSON serialize와 생성자 - Builder 관련

Jieun·2024년 6월 30일

프로젝트 기록

목록 보기
2/5
post-thumbnail

제목이 굉장히 장황하다..

JSON -> POJO (자바객체) : deserialize

  • @RequestBody로 넘어온 JSON -> java Object로의 변환 수행 : Jackson2HttpMessageConverter
  • converter 내부에서 ObjectMapper.readvalue() 호출
  • readvalue : JsonDeserializer를 찾고 해당 JsonDeserializer로 deserialize(역직렬화)를 해서 Object를 반환
    • 이 과정에서 "기본생성자"를 사용해 object를 생성하고 -> 그 후에 값을 주입
      1. field가 public 이거나
      2. private인 경우 setter or getter 둘 중 하나가 필요함
      3. 기본생성자는 항상 필수
  • 하지만 spring을 사용하는 경우, 내부에 jackson-module-parameter-names 모듈을 포함함 : 기본생성자가 없어도 다른 생성자에 역할을 위임하여 수행
  • 인자가 1개인 생성자만 존재하는 경우엔 binding error 발생
    : @Jacksonized / @JsonCreator 사용해 해결 필요

- 생성자 선택 전략

1. 기본생성자가 존재하는 경우

  • 기본생성자를 사용해 생성 : createUsingDefault

2. 프로퍼티 생성자 : 어떤 생성자 이용할 지 명시하는 방법

  • @JsonCreator & @JsonProperty or @ConstructorProperties

  • deserializefromObjectUsingNonDefault -> deserializeUsingPropertyBasedProperty 호출

@Builder와 생성자 - 직렬화

if a member is annotated, it must be either a constructor or a method. If a class is annotated, then a package-private constructor is generated with all fields as arguments (as if @AllArgsConstructor(access = AccessLevel.PACKAGE) is present on the class), and it is as if this constructor has been annotated with @Builder instead. Note that this constructor is only generated if you haven't written any constructors and also haven't added any explicit @XArgsConstructor annotations. In those cases, lombok will assume an all-args constructor is present and generate code that uses it; this means you'd get a compiler error if this constructor is not present.

즉 빌더는 클래스 레벨에 붙은 경우에는 다른 생성자가 없는 경우에만 전체생성자를 자동으로 붙여준다

  • 그러므로 @Builder + @NoArgsConstructor -> 전체생성자가 없으므로 컴파일에러
  • @Builder + @NoArgsConstructor + @AllArgsConstructor -> OK
  • @Builder or @AllArgsConstructor : compile 에러는 없지만, 직렬화와 관련하여 오류발생
    - lombok에서 모든 인자를 받는 생성자를 붙여주는 경우, 직렬화에 이를 사용할 수 있도록 자동으로 @ConstructorProperties를 붙여줬었지만, 이 부분이 삭제되어 직렬화 과정에 오류 발생
    • 따라서 Builder 사용과 직렬화를 둘 다 수행해야 하는 경우에는 @Buider + @NoArgsConstructor (직렬화에 사용할 기본생성자) + @AllArgsConstructor (기본생성자가 존재하므로 전체생성자를 명시적으로 생성해야 함)을 사용하거나,
    • 사용할 프로퍼티 생성자를 직접 작성해주자

참고링크

0개의 댓글