내가 소스 코드를 제어 할 수없는 속성을 무시하도록 jackson에게 어떻게 알릴 수 있습니까?


112

간단히 말해서, 내 엔티티 중 하나에는 "getBoundary"를 호출 할 때 예외를 발생 시키는 GeometryCollection 이 있습니다 (이 책의 이유는 다른 책입니다. 지금은 이것이 작동하는 방식이라고 가정 해 보겠습니다).

특정 게터를 포함하지 않도록 Jackson에게 말할 수있는 방법이 있습니까? 코드를 소유 / 제어 할 때 @JacksonIgnore를 사용할 수 있다는 것을 알고 있습니다. 그러나 이것은 사실이 아닙니다. jackson은 부모 객체의 연속적인 직렬화를 통해이 지점에 도달합니다. jackson 문서에서 필터링 옵션을 보았습니다. 그럴듯한 해결책입니까?

감사!

답변:


168

Jackson Mixins 를 사용할 수 있습니다 . 예를 들면 :

class YourClass {
  public int ignoreThis() { return 0; }    
}

이 Mixin으로

abstract class MixIn {
  @JsonIgnore abstract int ignoreThis(); // we don't need it!  
}

이것으로 :

objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);

편집하다:

주석 덕분에 Jackson 2.5 이상에서는 API가 변경되었으며 다음과 같이 호출해야합니다. objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)


1
그리고 속성이 기계 생성이고 이름에 지원되지 않는 문자가있는 경우? 처럼 '@'? JVM은 허용하지만 Java 컴파일러는 허용하지 않습니다. Jackson이 이에 대한 해결책을 가지고 있습니까?
마크

3
그리고 잭슨 2.2에서는objectMapper.addMixInAnnotations(Class<?> target, Class<?> mixinSource);
CorayThan

getter 대신 속성 이름을 지정하여 어떻게 무시합니까?
Erran Morad

68

또 다른 가능성은 알려지지 않은 모든 속성을 무시하려는 경우 다음과 같이 매퍼를 구성 할 수 있다는 것입니다.

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

5
특정 속성 만 무시하도록 objectMapper를 구성 할 수 있다면 좋을 것입니다. 즉, 'myfield'라고 말할 수있는 것을 제외하고 모든 새로운 / 알 수없는 필드에 대한 예외를보고합니다. 같은 것mapper.configure(DeserializationFeature.failOnUnknownPropertiesExcep(new String[] {"myField"}));
ms_27

다음 without()과 같이 리더에서 구성 할 수도 있습니다 .mapper.reader().without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
Drew Stephens

이 메커니즘을 사용하지 않는 것이 좋습니다. 잭슨의 "엄격한"사고 방식은 알려지지 않은 / 처리되지 않은 필드에서 오류가 발생하는 원인 중 하나이며 Java의 정적으로 유형화 / 컴파일 시간 분석 된 특성과 잘 일치합니다. 대신 지정된 무시 된 필드 집합을 처리하지 않도록 선택하는 것이 훨씬 좋습니다.
Per Lundberg

26

Java 클래스 사용

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

주석 사용

@JsonIgnoreProperties(ignoreUnknown=true)

11

주석 기반 접근 방식이 더 좋습니다. 그러나 때때로 수동 조작이 필요합니다. 이를 위해 ObjectWriter 메서드 없이 사용할 수 있습니다 .

ObjectMapper mapper   = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
String       jsonText = writer.writeValueAsString(sourceObject);

9
이 접근 방식은 나에게 적합하지 않지만 mixin 방식은 작동합니다. 직렬화 후에도 여전히 무시 된 속성을 얻습니다. withoutAttribute ()가 있는데 왜 믹스 인이 있는가?
Erran Morad 2019

9

믹스 인 주석은 이미 언급했듯이 여기에서 잘 작동합니다. 속성 별 @JsonIgnore 이상의 또 다른 가능성은 포함해서는 안되는 유형이있는 경우 (즉, GeometryCollection 속성의 모든 인스턴스를 무시해야하는 경우) @JsonIgnoreType을 사용하는 것입니다. 그런 다음 직접 추가하거나 (유형을 제어하는 ​​경우) 다음과 같이 믹스 인을 사용하여 추가 할 수 있습니다.

@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule

이는 모두 단일 'IgnoredType getContext ()'접근자를 갖는 많은 클래스가있는 경우에 더 편리 할 수 ​​있습니다 (많은 프레임 워크의 경우).


5

비슷한 문제가 있었지만 Hibernate의 양방향 관계와 관련이 있습니다. 나는 어떤 관점을 다루고 있는지에 따라 관계의 한쪽을 보여주고 다른 쪽은 프로그래밍 방식으로 무시하고 싶었습니다. 그렇게 할 수 없다면 불쾌한 StackOverflowExceptions로 끝납니다 . 예를 들어, 이런 물건이 있다면

public class A{
  Long id;
  String name;
  List<B> children;
}

public class B{
  Long id;
  A parent;
}

parentA를보고 있으면 B 의 필드 를 프로그래밍 방식으로 무시하고 B를보고 있으면 A의 children필드를 무시하고 싶습니다.

나는 이것을하기 위해 믹스 인을 사용하기 시작했지만 그것은 매우 빨리 끔찍 해졌다. 데이터 형식을 지정하기 위해 존재하는 쓸모없는 클래스가 너무 많습니다. 나는 이것을 더 깔끔한 방식으로 처리하기 위해 내 자신의 직렬 변환기를 작성했다 : https://github.com/monitorjbl/json-view .

무시할 필드를 프로그래밍 방식으로 지정할 수 있습니다.

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

List<A> list = getListOfA();
String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(B.class, match()
        .exclude("parent")));

또한 와일드 카드 매처를 통해 매우 단순화 된보기를 쉽게 지정할 수 있습니다.

String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(A.class, match()
        .exclude("*")
         .include("id", "name")));

제 원래의 경우 이와 같은 단순한보기의 필요성은 부모 / 자식에 대한 최소한의 정보를 표시하는 것이었지만 역할 기반 보안에도 유용했습니다. 개체에 대한 더 적은 정보를 반환하는 데 필요한 권한이 낮은 개체보기

이 모든 것은 serializer에서 나왔지만 내 앱에서 Spring MVC를 사용하고있었습니다. 이러한 경우를 제대로 처리하기 위해 기존 Spring 컨트롤러 클래스에 드롭 할 수있는 통합을 작성했습니다.

@Controller
public class JsonController {
  private JsonResult json = JsonResult.instance();
  @Autowired
  private TestObjectService service;

  @RequestMapping(method = RequestMethod.GET, value = "/bean")
  @ResponseBody
  public List<TestObject> getTestObject() {
    List<TestObject> list = service.list();

    return json.use(JsonView.with(list)
        .onClass(TestObject.class, Match.match()
            .exclude("int1")
            .include("ignoredDirect")))
        .returnValue();
  }
}

둘 다 Maven Central에서 사용할 수 있습니다. 나는 그것이 다른 누군가에게 도움이되기를 바랍니다. 이것은 내 사건에 대한 좋은 해결책이 없었던 Jackson의 특히 추악한 문제입니다.


수입이란 무엇입니까 Match.match()?
Pasupathi Rajamanickam

2

클래스의 특정 속성을 항상 제외하려면 다음 setMixInResolver메서드를 사용할 수 있습니다 .

    @JsonIgnoreProperties({"id", "index", "version"})
    abstract class MixIn {
    }

    mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
        @Override
        public Class<?> findMixInClassFor(Class<?> cls) {
            return MixIn.class;  
        }

        @Override
        public ClassIntrospector.MixInResolver copy() {
            return this;
        }
    });

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.