2012-02-21 2 views
11

@JsonFilter 주석이 런타임에 사용되는시기를 선택적으로 결정할 수 있습니까?@JsonFilter throw "JsonMappingException : BeanPropertyFilter를 해결할 수 없습니다"

필터를 제공하지 않을 때 JsonMappingException 예외가 발생합니다 (아래 참조).

배경 :

가 나는 동적으로 빈 속성 직렬화하기 필터링 @JsonFilter를 사용할 수있는 recent StackOverflow post에서 배웠습니다. 이것은 잘 작동합니다.

// shortened for brevity 
FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 

return mapper.filteredWriter(filters).writeValueAsString(user); 

문제 : 내 도메인 클래스에 내 JAX-RS 서비스에서이 코드를합니다 (CXF 구현을 사용)의 추가로 @JsonFilter("apiFilter")를 추가 한 후, 동적으로 내 편안하고 API에 의해 반환되는 속성을 필터링 할 수 있어요 필터를 전혀 적용하지 않으려는 다른 서비스 호출이있는 것입니까? 이 경우 모든 속성을 필터링하지 않고 전체 도메인 클래스를 반환하려고합니다.

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not resolve BeanPropertyFilter with id 'apiFilter'; no FilterProvider configured 

at org.codehaus.jackson.map.ser.BeanSerializer.findFilter(BeanSerializer.java:252) 
at org.codehaus.jackson.map.ser.BeanSerializer.serializeFieldsFiltered(BeanSerializer.java:216) 
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:140) 

답변

6

난 당신이 모든 속성을 원하는 곳에 당신이 경우에 빈 직렬화 필터를 정의하는 필터링 작가를 속일 수 있다고 생각 : 경우에 그냥 다음과 같이 내가 예외를 받고 있어요 도메인 클래스를 반환하려고 곳 seralized : 엔진이 @JsonFilter 말뭉치 주석에 정의 된 "apiFilter"필터를 찾습니다

FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.serializeAllExcept(emptySet)); 

이 방법은, 그것을 발견하지만 (모든 속성을 직렬화합니다으로) 영향을주지 않습니다.

편집 또한, 당신은 filteredWriter() 대신 팩토리 메소드 writer()를 호출 할 수

ObjectWriter writer=null; 
if(aplyFilter) { 
    FilterProvider filters = new SimpleFilterProvider().addFilter("apiFilter", SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties)); 
    writer=mapper.filteredWriter(filters); 
} else { 
    writer=mapper.writer(); 
} 

return writer.writeValueAsString(user); 

나는 참으로 더 나은이 마지막 솔루션이 방식 청소기라고 생각합니다.

+0

편집 한 예제에서 모든 jax-rs 서비스 호출에서 호출 할 작성기 메소드를 확인하는 코드를 포함해야합니까? 일부 서비스 메소드에서는 String이 아닌 실제 User 객체를 반환합니다. 많은 의견을 보내 주셔서 감사합니다! – Justin

+1

좋아, 나는 그것을 시험해 볼 기회가 있었다. 당신이 제안한 "속임수"는 작동하지만 두 번째 "청결한"제안은 작동하지 않습니다. 이 경우 나는 여전히 "No FilterProvider configured"오류를 수신합니다. 다시 한 번 감사드립니다. – Justin

+0

@ Justin : 글쎄, IMO는 문제를 해결하는 "더러운"해결 방법이 작동하지 않는 "깨끗한"방법보다 낫습니다. :) 희망을 당신의 문제를 해결하는 데 도움이. –

18

나는 이미 답 것을 알고 있지만 초보자 함수 잭슨은 실제로 실종 필터 (JACKSON-650)에 실패 할 수있는 기능이 추가되었습니다 : 당신은 그냥 SimpleFilterProvider.setFailOnUnknownId(false)를 호출해야하고이 예외을받지 않습니다
을.

+0

대답 해 주셔서 감사합니다. 유용하다 – Justin

+4

물론 매퍼에서 필터링을 전혀 사용하지 않더라도 SimpleFilterProvider를 구성해야한다. 오, 그럼. – Jules

0

나는 동일한 예외를 얻는 데 동일한 예외가 있었지만 허용 된 대답은 내 경우에 도움이되지 못했습니다.

내 설정에서

내가 같이 사용자 정의 JacksonSerializer를 사용했다 : 여기에 나를 위해 일한 솔루션의

@JsonSerialize(using = MyCustomSerializer.class) 
private Object someAttribute; 

는 그리고 시리얼 라이저는 다음과 같이 구현 :

public class MyCustomSerializer extends JsonSerializer<Object> { 
    @Override 
    public void serialize(Object o, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
    if (o != null) { 
     jgen.writeObject(o); 
    } 
    } 
} 

이의 문제 필터를 사용하지 않는 한 작동합니다. 예를 들어 jgen.writeString(..)을 사용하는 경우와 같이 프리미티브를 serialize하는 경우에도 작동합니다. 필터를 사용하는 경우 필터는 JsonGenerator이 아닌 SerializerProvider의 어딘가에 저장되기 때문에 잘못되었습니다. 이 경우 jsongenerator를 직접 사용하면 필터에 대해 알지 못하는 새 SerializerProvider가 내부적으로 만들어집니다. 따라서 더 짧은 jgen.writeObject(o) 대신 provider.defaultSerializeValue(o, jgen)으로 전화해야합니다.그러면 필터가 손실되지 않고 적용될 수 있습니다.

관련 문제