2017-03-25 2 views
0

JSON 파일의 내용에 따라 수퍼 클래스 또는 하위 클래스로 비 순차적으로 변환하려고합니다. 그것은 다음과 같습니다 경우 Jackson과 JSON 파일의 다형성 직렬화

{ 
    "id":"123", 
    "title":"my title", 
    "body":"my body" 
} 

또는 서브 클래스에

이 : 그것은 다음과 같습니다 경우

그것은 슈퍼 클래스에 직렬화되어야한다

{ 
    "id":"123", 
    "title":"my title", 
    "body":"my body", 
    "tags":["tag1", "tag2"] 
} 

그래서 유일한 차이점은 tags 배열, 이를 String 배열로 직렬화해야합니다. 그러나 POST 요청을 통해 Jersey (Dropwizard)에서 deserialization을 트리거하면 {"code":400,"message":"Unable to process JSON"}을 반환합니다.

는 슈퍼 클래스입니다 :

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME) 
@JsonSubTypes({ @JsonSubTypes.Type(name = "subdocument", value = SubDocument.class) }) 
public class SuperDocument { 

private String id; 
private String title; 
private String body; 

public SuperDocument() { 

} 

@JsonCreator 
public SuperDocument(@JsonProperty("id") String id, @JsonProperty("title") String title, @JsonProperty("body") String body) { 
    this.id = id; 
    this.title = title; 
    this.body = body; 
} 

@JsonProperty("id") 
public String getId() { 
    return id; 
} 

@JsonProperty("id") 
public void setId(String id) { 
    this.id = id; 
} 

... the other getters and setters ... 
} 

이것은 서브 클래스 :

@JsonTypeName("subdocument") 
public class SubDocument extends SuperDocument { 

private String[] tags; 

public SubDocument() { 

} 

@JsonCreator 
public SubDocument(@JsonProperty("id") String id, @JsonProperty("title") String title, @JsonProperty("body") String body, @JsonProperty("tags") String[] tags) { 
    super(id, title, body); 
    this.tags = tags; 
} 

@JsonProperty("tags") 
public String[] getTags() { 
    return tags; 
} 

@JsonProperty("tags") 
public void setTags(String[] tags) { 
    this.tags = tags; 
} 
} 

가 내가 뭘 잘못 알고 계십니까?

답변

1

JsonTypeInfo에는 하위 클래스/수퍼 클래스를 식별 할 수있는 속성이 필요합니다. 예를 들어 아래 그림과 같이

{ 
    "id":"123", 
    "title":"my title", 
    "body":"my body", 
    "type":"superdocument" 
} 

{ 
    "id":"123", 
    "title":"my title", 
    "body":"my body", 
    "tags":["tag1", "tag2"], 
    "type":"subdocument" 
} 

그런 다음 SuperDocument 주석을 수정합니다. 당신이 추가 속성 "유형"을 intrduce하지 않으려면

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,property="type") 
@JsonSubTypes({ @JsonSubTypes.Type(name = "subdocument", value = SubDocument.class),@JsonSubTypes.Type(name = "superdocument", value = SuperDocument.class) }) 

public class SuperDocument { 

} 

는, 당신은 아래 그림과 같이 사용자 정의 형의 해결 및 유형 디시리얼라이저를 작성 할 수 있습니다.

@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) 
@JsonTypeResolver(DocumentTypeResolver.class) 
public class SuperDocument { 

} 
추가 식별 속성은 속임수를 썼는지
+0

아래와 같이

public class DocumentTypeResolver extends StdTypeResolverBuilder { @Override public TypeDeserializer buildTypeDeserializer( final DeserializationConfig config, final JavaType baseType, final Collection<NamedType> subtypes) { return new DocumentDeserializer(baseType, null, _typeProperty, _typeIdVisible, _defaultImpl); } } 

사용자 정의 TypeDeserializer이

public static class DocumentDeserializer extends AsPropertyTypeDeserializer { public DocumentDeserializer(final JavaType bt, final TypeIdResolver idRes, final String typePropertyName, final boolean typeIdVisible, final Class<?> defaultImpl) { super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl); } public DocumentDeserializer(final AsPropertyTypeDeserializer src, final BeanProperty property) { super(src, property); } @Override public TypeDeserializer forProperty(final BeanProperty prop) { return (prop == _property) ? this : new DocumentDeserializer(this, prop); } @Override public Object deserializeTypedFromObject(final JsonParser jp, final DeserializationContext ctxt) throws IOException { JsonNode node = jp.readValueAsTree(); Class<?> subType =null; JsonNode tags = node.get("tags"); if (tags == null) { subType=SuperDocument.class; } else { subType=SubDocument.class; } JavaType type = SimpleType.construct(subType); JsonParser jsonParser = new TreeTraversingParser(node, jp.getCodec()); if (jsonParser.getCurrentToken() == null) { jsonParser.nextToken(); } JsonDeserializer<Object> deser = ctxt.findContextualValueDeserializer(type, _property); return deser.deserialize(jsonParser, ctxt); } } 

이제 SuperDocument 클래스에 주석을, 감사합니다! – phly