Spring - Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from `StreamWriteConstraints.getMaxNestingDepth()`)

송민지·2024년 8월 26일

spring

목록 보기
3/4

문제 발생

Entity

// Post entity
package com.sparta.schedule.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sparta.schedule.dto.PostRequestDto;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@Setter
@Table(name ="post")
@NoArgsConstructor

public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "POST_ID")
    private Integer postId;

    private String password;
    private String username;
    private String title;
    private String contents;

    @CreatedDate
    private LocalDateTime created_at;
    @LastModifiedDate
    private LocalDateTime updated_at;

    @OneToMany(mappedBy = "post")
    private List<Comment> commentList = new ArrayList<>();

    public void addCommentList(Comment comment){
        this.commentList.add(comment);
        comment.setPost(this);
    }

    public Post(PostRequestDto requestDto) { //데이터 저장
        this.password= requestDto.getPassword();
        this.title = requestDto.getTitle();
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
        this.created_at = LocalDateTime.now();
        this.updated_at = LocalDateTime.now();
    }

    public void update(PostRequestDto requestDto){
        this.title = requestDto.getTitle();
        this.contents = requestDto.getContents();
        this.updated_at = LocalDateTime.now();
    }

}
package com.sparta.schedule.entity;

import com.sparta.schedule.dto.CommentRequestDto;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.LocalDateTime;

@Entity
@Getter
@Setter
@Table(name ="comment")
@NoArgsConstructor
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer commentId;
    private String contents;
    private String username;

    @CreatedDate
    private LocalDateTime createdAt;
    @LastModifiedDate
    private LocalDateTime updatedAt;

    @ManyToOne
    @JoinColumn(name = "POST_ID")
    private Post post;


    public Comment(CommentRequestDto requestDto) {//데이터 저장
        this.contents = requestDto.getContents();
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
        this.username = requestDto.getUsername();
    }

    public void update(CommentRequestDto requestDto) {
        this.contents = requestDto.getContents();
        this.updatedAt = LocalDateTime.now();
        this.username = requestDto.getUsername();
    }
}

controller와 service

//controller 
@GetMapping("")
    public List<Comment> getAllComment(){
        return this.commentService.getComments();
    }
    
//service
public List<Comment>  getComments(){
        List<Comment> comment = commentRepository.findAll();
        return comment;
    }

오류발생

Post entity와 Comment entity를 양방향 매핑하면서 Postman으로 Post나 comment에 get요청을 하면

사진과 같은 오류가 발생했습니다. 오류의 원인을 읽어보면
Could not write JSON: Document nesting depth (1001) exceeds the maximum allowed (1000, from StreamWriteConstraints.getMaxNestingDepth())
그까이꺼 정신으로 대애충 해석해보자면 '1001이 넘는 깊이로 인해 JSON 생성에 실패했다'로 읽을 수 있겠군요 하핫

오류의 원인은 entity의 양방향 mapping이였습니다. 서로의 데이터를 참조하다 보니 Post entity불러오고 다시 comment entity를 불러오면서 무한재귀 데이터가 만들어졌습니다.

크아아악 저게 대체 뭐야

해결방법

  1. 참조하는 엔티티에서 재귀를 일으키는 필드에 @JsonIgnore를 붙여준다.
  2. RestController에서 엔티티를 바로 반환하지 않고, DTO를 사용한다.

Post entity에서 comment와 mapping된 entity에 @JsonIgnore 데코레이터를 추가하였습니다.
@JsonIgnore는 직렬화 및 역직렬화에 사용되는 논리적 속성을 무시하는데 사용되는 데코레이터입니다. getter, setter는 물론 field에서도 사용할 수 있습니다
라고 하는데 뭔말인지 잘 몰라 더 찾아봤습니다.
논리적 속성을 무시한다는 말은 직렬화/역직렬화할 경우 해당 column을 무시한다는 말이였습니다.


@JsonIgnore를 Post entity에서 comment를 참조하는 column에 생성하고 다시 get 요청을 하니 잘 데이터가 잘 넘어왔습니다.


profile
항상 밝게

0개의 댓글