복붙노트

[SPRING] Spring : 하나의 JPA 모델, 많은 JSON 표현

SPRING

Spring : 하나의 JPA 모델, 많은 JSON 표현

저는 Spring / JPA를 사용하여 RESTful 웹 서비스를 작성하고 있습니다. 웹 서비스를 통해 노출되는 JPA 모델이 있습니다. '코스'모델은 꽤 넓습니다. 실제로는 일반 정보, 가격 세부 정보 및 일부 캐시와 같은 몇 가지 데이터 세트로 구성됩니다.

내가 만나는 문제는 동일한 JPA 모델을 사용하여 다른 JSON 표현을 발행 할 수 없다는 것입니다.

첫 번째 경우에는 코스의 general_info 데이터 집합 만 반환하면됩니다.

GET / api / courses / general_info

두 번째 경우에는 가격 데이터 집합 만 반환하려고합니다.

GET / api / courses / pricing

이 문제를 해결하는 방법은 다음과 같습니다. 특정 순서가 아닙니다.

어떤 접근 방식을 권하고 싶습니까?

해결법

  1. ==============================

    1.Spring Data REST 2.1에는이 목적을위한 새로운 메커니즘이있다. - Projections (이제 스프링 데이터 커먼즈의 일부이다).

    Spring Data REST 2.1에는이 목적을위한 새로운 메커니즘이있다. - Projections (이제 스프링 데이터 커먼즈의 일부이다).

    정확하게 노출 된 필드를 포함하는 인터페이스를 정의해야합니다.

    @Projection(name = "summary", types = Course.class)
    interface CourseGeneralInfo {
    
      GeneralInfo getInfo();
    
    }
    

    그런 다음 Spring은 소스에서 자동으로이를 찾을 수 있으며 다음과 같이 기존 엔드 포인트에 요청할 수 있습니다.

    GET /api/courses?projection=general_info
    

    기준 https://spring.io/blog/2014/05/21/what-s-new-in-spring-data-dijkstra

    투영 된 스프링 샘플 프로젝트 : https://github.com/spring-projects/spring-data-examples/tree/master/rest/projections

  2. ==============================

    2.주석을 통해 다른 뷰를 사용할 수있게 해주는 Spring 4.1의 멋진 기능에 대해 읽었습니다.

    주석을 통해 다른 뷰를 사용할 수있게 해주는 Spring 4.1의 멋진 기능에 대해 읽었습니다.

    from : https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

    public class View {
        interface Summary {}
    }
    
    public class User {
    
        @JsonView(View.Summary.class)
        private Long id;
    
        @JsonView(View.Summary.class)
        private String firstname;
    
        @JsonView(View.Summary.class)
        private String lastname;
    
        private String email;
        private String address;
        private String postalCode;
        private String city;
        private String country;
    }
    
    public class Message {
    
        @JsonView(View.Summary.class)
        private Long id;
    
        @JsonView(View.Summary.class)
        private LocalDate created;
    
        @JsonView(View.Summary.class)
        private String title;
    
        @JsonView(View.Summary.class)
        private User author;
    
        private List<User> recipients;
    
        private String body;
    }
    

    Spring MVC @JsonView 지원 덕분에 핸들러 메서드 기반으로 어떤 필드를 직렬화할지 선택할 수있다.

    @RestController
    public class MessageController {
    
        @Autowired
        private MessageService messageService;
    
        @JsonView(View.Summary.class)
        @RequestMapping("/")
        public List<Message> getAllMessages() {
            return messageService.getAll();
        }
    
        @RequestMapping("/{id}")
        public Message getMessage(@PathVariable Long id) {
            return messageService.get(id);
        }
    }
    

    이 예에서 모든 메시지가 검색되면 @JsonView (View.Summary.class)로 주석 된 getAllMessages () 메소드 덕분에 가장 중요한 필드 만 직렬화됩니다.

    [ {
      "id" : 1,
      "created" : "2014-11-14",
      "title" : "Info",
      "author" : {
        "id" : 1,
        "firstname" : "Brian",
        "lastname" : "Clozel"
      }
    }, {
      "id" : 2,
      "created" : "2014-11-14",
      "title" : "Warning",
      "author" : {
        "id" : 2,
        "firstname" : "Stéphane",
        "lastname" : "Nicoll"
      }
    }, {
      "id" : 3,
      "created" : "2014-11-14",
      "title" : "Alert",
      "author" : {
        "id" : 3,
        "firstname" : "Rossen",
        "lastname" : "Stoyanchev"
      }
    } ]
    

    Spring MVC 기본 설정에서 MapperFeature.DEFAULT_VIEW_INCLUSION은 false로 설정된다. 즉, JSON View를 활성화하면 본문이나받는 사람과 같은 주석이 달린 필드 나 속성이 직렬화되지 않습니다.

    특정 메시지가 getMessage () 핸들러 메소드 (JSON 뷰가 지정되지 않음)를 사용하여 검색되면 모든 필드가 예상대로 직렬화됩니다.

    {
      "id" : 1,
      "created" : "2014-11-14",
      "title" : "Info",
      "body" : "This is an information message",
      "author" : {
        "id" : 1,
        "firstname" : "Brian",
        "lastname" : "Clozel",
        "email" : "bclozel@pivotal.io",
        "address" : "1 Jaures street",
        "postalCode" : "69003",
        "city" : "Lyon",
        "country" : "France"
      },
      "recipients" : [ {
        "id" : 2,
        "firstname" : "Stéphane",
        "lastname" : "Nicoll",
        "email" : "snicoll@pivotal.io",
        "address" : "42 Obama street",
        "postalCode" : "1000",
        "city" : "Brussel",
        "country" : "Belgium"
      }, {
        "id" : 3,
        "firstname" : "Rossen",
        "lastname" : "Stoyanchev",
        "email" : "rstoyanchev@pivotal.io",
        "address" : "3 Warren street",
        "postalCode" : "10011",
        "city" : "New York",
        "country" : "USA"
      } ]
    }
    

    @JsonView 주석으로 하나의 클래스 또는 인터페이스 만 지정할 수 있지만 상속을 사용하여 JSON 뷰 계층 구조를 나타낼 수 있습니다 (필드가 JSON 뷰의 일부인 경우 부모 뷰의 일부이기도 함). 예를 들어,이 핸들러 메소드는 @JsonView (View.Summary.class) 및 @JsonView (View.SummaryWithRecipients.class)로 주석 된 필드를 직렬화합니다.

    public class View {
        interface Summary {}
        interface SummaryWithRecipients extends Summary {}
    }
    
    public class Message {
    
        @JsonView(View.Summary.class)
        private Long id;
    
        @JsonView(View.Summary.class)
        private LocalDate created;
    
        @JsonView(View.Summary.class)
        private String title;
    
        @JsonView(View.Summary.class)
        private User author;
    
        @JsonView(View.SummaryWithRecipients.class)
        private List<User> recipients;
    
        private String body;
    }
    
    @RestController
    public class MessageController {
    
        @Autowired
        private MessageService messageService;
    
        @JsonView(View.SummaryWithRecipients.class)
        @RequestMapping("/with-recipients")
        public List<Message> getAllMessagesWithRecipients() {
            return messageService.getAll();
        }
    }
    
  3. from https://stackoverflow.com/questions/28447922/spring-one-jpa-model-many-json-respresentations by cc-by-sa and MIT license