2012-01-11 3 views
4

Jackson을 사용하여 JSON에서 역 직렬화해야하는 클래스가 있습니다. 클래스 구조는 다음과 같습니다.Jackson : 던지는 대신 속성 무시 JsonMappingException

public class A { 
    public B b; 
} 

public class B { 
    public List<C> c; 
} 

public class C { 
    public String s; 
    public Long l1; 
    public Long l2; 
    public Long l3; 
} 

객체의 직렬화가 대부분 잘 작동합니다. 을 제외하고는이고 목록이 비어있을 때 잘못된 값을 방출하는 버그가있는 코드와 상호 작용합니다. 그 대신에 방사된다 :

{ "b" : { "c" : [] } } 

그것을 방출 : 물론,이 모든 말이

org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token 
at [Source: [[email protected]; line: 1, column: 896] (through reference chain: A["b"]->B["c"]) 

:이 발생하면

{ "b" : { "c" : {} } } 

잭슨이 예외를 던진다. 입력이 잘못되었습니다.

그러나이 경우 빈 목록은 코드와 관련이 없습니다. 그것이 null이라면 나는 상관하지 않을 것이다. 역 직렬화가 불가능한 경우 Jackson이이 속성을 무시하도록 (그리고 null을 저장하도록) 말할 수있는 방법이 있습니까?

public class CListDeserializer extends JsonDeserializer<List<C>> 
{ 
    public CListDeserializer() { } 

    @Override 
    public List<C> deserialize(JsonParser arg0, 
     DeserializationContext arg1) throws IOException, 
      JsonProcessingException 
    { 
     try 
     { 
      return arg0.readValueAs(new TypeReference<List<C>>(){}); 
     } 
     catch (JsonMappingException jme) 
     { 
     } 
     return null; 
    } 
} 

그리고 필드에 주석을 추가하는 경우 :

org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class asgard.ChangeEntry] from JSON String; no single-String constructor/factory method (through reference chain: A["b"]) 

:

@JsonDeserialize(using=CListDeserializer.class) 
public List<C> c; 

내가 대신 예외가

나는 사용자 정의 디시리얼라이저를 사용하여 시도했다 비 직렬화를 시도하면이 예외 이 발생합니다. 그는 외부 형식 A - B에 대한 내부 serialize 된 값을 끌어서 deserialize 경우 제대로 작동합니다.

+0

하나 개 이상의 데이터 포인트 : 클래스 B는 같은 이름을 가진 열거 필드가 A에서'B '에 대한 참조로 :'public EnumType b'. 잭슨이 내부 유형 인 'B'를 비 직렬화 할 때, 혼란스러워서 'A'로 비 직렬화하려고 시도하고 있습니다. –

답변

2

사용자 지정 디시리얼라이저가 작동하지 않는 이유를 알아 냈습니다. readValueAs 메서드는 {을 사용하므로 예외가 발생하고 }은 다음 토큰으로 남습니다. 그러면 내부 객체가 닫히고 파서는 다음에 발생하는 열거 형 값을 열거 형이 아닌 내부 유형으로 파싱해야한다고 생각합니다.

나는이 내일 시도 할 것이다, 그러나 나는 deserialize 방법에 갈 수있는 방법이 생각 :

ObjectMapper om = ...; 

JsonNode node = arg0.readValueAs(JsonNode.class); 
try 
{ 
    return om.readValue(node, new TypeReference<List<C>>(){}); 
} 
catch (JsonMappingException jme) 
{ 
} 
return null; 
+0

좋아요. 'arg0.readValueAs (JsonNode.class)'가 작동하지 않으면'arg0.readValueAsTree()'를 시도해 볼 수 있으며, JsonNode도 리턴합니다. – waxwing

+0

그래, 잘됐다. –

관련 문제