我很难使用Spring-boot为Synology FileStation API创建REST客户端。 实际上,API使用相同的属性来存储不同类型的对象。 使用的属性是 data ,它可以存储 sid 或文件共享之类的搜索结果的内容。
对于搜索结果:
{
"data": {
"offset": 0,
"shares": [
{
"isdir": true,
"name": "config",
"path": "/config"
},
...
],
"total": 19
},
"success": true
}
对于登录结果:
{
"data": {
"sid": "blablablabla",
},
"success": true
}
对于严重的登录错误:
{
"error": {
"code": 400,
},
"success": false
}
我试图为每种类型的响应设计模型,但是我找不到使用Jackson进行反序列化的正确方法。
为简单起见,用于接收响应的类是 Response ,在响应中有一个成功字段和另外两个字段:数据和错误。 根据响应,要实例化的数据是 LoginResponse 或 ListShares 对象。
这是我班级的代码:
@JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
@JsonProperty("success")
private boolean success;
@JsonProperty(value = "data")
private Data data;
@JsonProperty(value = "error")
private Error error;
...
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Error {
private int code;
private Collection<ErrorInfo> errors;
public Error( int code, Collection<ErrorInfo> errors) {
super();
this.code = code;
this.errors = errors;
}
...
}
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
@JsonSubTypes.Type(value = LoginResponse.class),
@JsonSubTypes.Type(value = ListShares.class),
})
public abstract class Data {
}
@JsonTypeName("LoginResponse")
public class LoginResponse extends Data {
@JsonProperty("sid")
private String sid;
public LoginResponse() {
super();
}
...
}
@JsonTypeName("ListShares")
public class ListShares extends Data {
@JsonProperty("offset")
private int offset;
@JsonProperty("total")
private int total;
@JsonProperty("shares")
private Set<Share> shares;
public ListShares() {
super();
}
public ListShares(int offset, int total, Set<Share> shares) {
super();
this.offset = offset;
this.total = total;
this.shares = shares;
}
我收到此异常:
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.heavyrage.syno.apis.genericresponses.Response]: missing type id property 'data'
at [Source: (PushbackInputStream); line: 1, column: 38]
at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:1794) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1323) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:303) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:166) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:107) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1209) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482) ~[jackson-databind-2.11.1.jar:2.11.1]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3487) ~[jackson-databind-2.11.1.jar:2.11.1]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:273) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
... 17 common frames omitted
有人知道是否可以正确地实例化 Data 对象(实例化LoginResponse或ListShare)以填充Response对象的“ data”属性?
答案 0 :(得分:0)
我终于从杰克逊问题追踪器中找到了这个答案。 关键是实例化Data对象时要调用的反序列化器,从而返回正确的实现类,而Jackson可以实例化它。
https://stackoverflow.com/a/50013090/1030527
无论如何,最好使用Response类的合成,因为它反映了它与Data和Error类的HasA关系。
对于Data类本身,将组合与Java接口一起使用会导致杰克逊试图实例化接口类而导致另一个异常。