복붙노트

[SPRING] Spring Rest 웹 서비스에서 돌아 오는 json 응답을 필터링하는 방법

SPRING

Spring Rest 웹 서비스에서 돌아 오는 json 응답을 필터링하는 방법

Spring Rest 웹 서비스에서 돌아 오는 json 응답을 필터링하는 방법.

맞춤 이벤트를 호출 할 때 이벤트 ID와 이벤트 이름 만 출력하면됩니다. 특정 이벤트에 대해 물어봐야 할 때 행사의 전체 내용을 보내십시오.

Class CustomEvent{

 long id;
 String eventName;
 Account createdBy;
 Account modifiedBy;
 ..


}

Class Account{
 long id;
 String fname;
 String lname;
 ....

}


@Controller
public class CustomEventService
{
    @RequestMapping("/customEvents")
    public @ResponseBody List<CustomEvent> getCustomEventSummaries() {}

    @RequestMapping("/customEvents/{eventId}")
    public @ResponseBody CustomEvent getCustomEvent(@PathVariable("eventId") Long eventId) {}
}

위의 목표는 어떻게 달성 할 수 있습니까? 나는 봄 3.1을 사용하고 있습니다. ther 이상의 버전을 달성하기 위해 3.1 버전의 모든 지원 여부

해결법

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

    1.@JsonFilter를 사용하여 아카이브 할 수 있습니다.

    @JsonFilter를 사용하여 아카이브 할 수 있습니다.

    Pojo :

    @JsonFilter("myFilter")
    public class User {
        ....
    }
    

    제어 장치:

    public String getUser(
                @RequestParam(value="id") String id, 
                @RequestParam(value="requiredFields",required=false ) String requiredFields
            ) throws JsonParseException, JsonMappingException, IOException {
    
        //Get User 
        User user = userService.getUser(id);
        //Start
        ObjectMapper mapper = new ObjectMapper();
        // and then serialize using that filter provider:
        String json="";
        try {
            if (requiredFields!= null) {
                String[] fields = requiredFields.split("\\,");
    
                FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
                SimpleBeanPropertyFilter.filterOutAllExcept(new HashSet<String>(Arrays
                      .asList(fields))));
    
                json = mapper.filteredWriter(filters).writeValueAsString(user);//Deprecated 
            } else {
                SimpleFilterProvider fp = new SimpleFilterProvider().setFailOnUnknownId(false);
                mapper.setFilters(fp);
                json =mapper.writeValueAsString(user);
            }
        } catch (JsonGenerationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        return json;
    }
    

    URL 가져 오기 : ..... & requiredFields = 아이디, 이름, 나이

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

    2.잭슨의 믹스 인 기능을 모두 활용하는 두 가지 솔루션을 생각해 볼 수 있습니다.

    잭슨의 믹스 인 기능을 모두 활용하는 두 가지 솔루션을 생각해 볼 수 있습니다.

    첫 번째 솔루션은 훨씬 복잡하지만 설명하는 내용이 코드의 다른 부분에 복제되는 경우이 링크에서 설명합니다. JsonFilter 주석에서 설정 한 특정 mixin (귀하의 경우 CustomEventMixin)을 적용하는 aspect를 정의하는 것이 발생합니다.

    두 번째 솔루션은 훨씬 간단하며 다음 코드와 같이 String 책임을 위임하지 않고 jackson 객체 매퍼를 직접 사용하는 것을 포함합니다

    @Controller
    public class EventController {
    
    
        private ObjectMapper objectMapper = new ObjectMapper();
    
        public EventController(ObjectMapper objectMapper) {
            this.objectMapper = objectMapper;
            objectMapper.addMixInAnnotations(CustomEvent.class, CustomEventMixin.class);
        }
    
        @RequestMapping("/customEvents")
        @ResponseBody
        public String suggest()  {
            return objectMapper.writeValueAsString(getCustomEvents(), new TypeReference<List<CustomEvent>>() {});
        }
    }
    

    두 경우 모두 Jackson 규칙에 따라 CustomEventMixin을 정의해야합니다.

    최신 정보:

    Mixin 클래스의 예는 (당신이 id를 무시하기를 원한다)

    public interface CustomEventMixin {
    
        String name;
    
        @JsonIgnore
        String id;
    }
    
  3. ==============================

    3.이 목적으로 @JsonView 어노테이션을 사용할 수 있습니다. 하지만 불행히도 4.x 이상에서만 작동합니다.

    이 목적으로 @JsonView 어노테이션을 사용할 수 있습니다. 하지만 불행히도 4.x 이상에서만 작동합니다.

    이것은 내가 아는 가장 깨끗한 방법입니다.

    public class View {
        public interface Summary {}
        public interface Details extends Summary{}
    }
    
    Class CustomEvent{
        @JsonView(View.Summary.class)
        long id;
    
        @JsonView(View.Summary.class)
        String eventName;
    
        @JsonView(View.Details.class)
        Account createdBy;
    
        @JsonView(View.Details.class)
        Account modifiedBy;
    }
    
    @Controller
    public class CustomEventService
    {
        @JsonView(View.Summary.class)
        @RequestMapping("/customEvents")
        public @ResponseBody List<CustomEvent> getCustomEventSummaries() {}
    
        @RequestMapping("/customEvents/{eventId}")
        public @ResponseBody CustomEvent getCustomEvent(@PathVariable("eventId") Long eventId) {}
    }
    

    기본적으로 @JsonView 주석이없는 필드도 직렬화됩니다. 그것이 모두에게 주석을 달 필요가있는 이유입니다.

    자세한 내용은 다음을 참조하십시오. https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

  4. ==============================

    4.나는 기존 프로젝트와 비슷한 요구 사항을 가지고 있었다. 하나의 객체가 여러 컨트롤러에 의해 사용됨에 따라 뷰를 도입하는 것은 어려웠습니다. 필터를 구현하는 것은 깨끗한 해결책도 아니 었습니다. 그래서 나는 그 값을 클라이언트에 보내기 전에 Controller의 DTO에서 지우기로 결정했습니다. 따라서 문제를 해결하기위한 내 자신의 몇 가지 방법 (실행 시간이 약간 더 소요될 수 있음).

    나는 기존 프로젝트와 비슷한 요구 사항을 가지고 있었다. 하나의 객체가 여러 컨트롤러에 의해 사용됨에 따라 뷰를 도입하는 것은 어려웠습니다. 필터를 구현하는 것은 깨끗한 해결책도 아니 었습니다. 그래서 나는 그 값을 클라이언트에 보내기 전에 Controller의 DTO에서 지우기로 결정했습니다. 따라서 문제를 해결하기위한 내 자신의 몇 가지 방법 (실행 시간이 약간 더 소요될 수 있음).

    public static void includeFields(Object object, String... includeFields) {
            for (PropertyDescriptor propertyDescriptor : PropertyUtils.getPropertyDescriptors(object)) {
                if (!Arrays.asList(includeFields).contains(propertyDescriptor.getName())) {
                    clearValues(object, propertyDescriptor);
                }
            }
        }
    
        public static void excludeFields(Object object, String... includeFields) {
            for (PropertyDescriptor propertyDescriptor : PropertyUtils.getPropertyDescriptors(object)) {
                if (Arrays.asList(includeFields).contains(propertyDescriptor.getName())) {
                    clearValues(object, propertyDescriptor);
                }
            }
        }
    
        private static void clearValues(Object object, PropertyDescriptor propertyDescriptor) {
            try {
                if(propertyDescriptor.getPropertyType().equals(boolean.class)) {
                    PropertyUtils.setProperty(object, propertyDescriptor.getName(), false);
                } else {
                    PropertyUtils.setProperty(object, propertyDescriptor.getName(), null);
                }
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                //TODO
                e.printStackTrace();
            }
        }
    

    Drawback은 항상 값을 가지며 따라서 페이로드에 존재할 부울 필드입니다. 최소한 이것은 동적 솔루션을 제공하고 페이로드의 많은 필드를 줄이는 데 도움이되었습니다.

  5. from https://stackoverflow.com/questions/22609079/how-to-filter-the-json-response-returning-from-spring-rest-web-service by cc-by-sa and MIT license