我试图修补一个与另一个多态对象有OneToOne关系的对象。拥有这种关系的对象看起来像这样(我省略了不相关的JPA注释和字段):
public class Policy extends BaseEntity {
@Valid
@NotNull
@OneToOne(optional = false, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, orphanRemoval = true)
@JoinColumn(name = "CHANNELFLOW_ID")
private ChannelFlowConfig channelFlow;
}
引用的对象如下所示:
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "CHANNELFLOWCONFIG")
public abstract class ChannelFlowConfig extends BaseEntity {
@JsonProperty("type")
public String getType() {
return getClass().getName();
}
}
子对象没有什么特别之处,只有一些不同的字段(上面省略了字段),它们没有存储库,而是全部通过PolicyRepository处理。 现在,当我尝试使用从/ policy / 2上的GET检索到完全相同内容的主体来修补策略时,我得到了以下异常:
Caused by: com.fasterxml.jackson.databind.JsonMappingException:
Unexpected token (END_OBJECT), expected FIELD_NAME: missing property 'type' that is to contain type id (for class com.vw.mbbc.authserver.model.policy.ChannelFlowConfig)
at [Source: N/A; line: -1, column: -1] (through reference chain: com.vw.mbbc.authserver.model.policy.Policy["channelFlow"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:1376) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.DeserializationContext.reportWrongTokenException(DeserializationContext.java:1197) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:165) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:105) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:209) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:502) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:104) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:240) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1628) ~[jackson-databind-2.8.9.jar:2.8.9]
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1301) ~[jackson-databind-2.8.9.jar:2.8.9]
at org.springframework.data.rest.webmvc.json.DomainObjectReader.doMerge(DomainObjectReader.java:222) ~[spring-data-rest-webmvc-2.5.5.RELEASE.jar:?]
at org.springframework.data.rest.webmvc.json.DomainObjectReader.read(DomainObjectReader.java:77) ~[spring-data-rest-webmvc-2.5.5.RELEASE.jar:?]
通过CocoaRest进行PATCHing时以及通过Retrofit进行PATCHing时会发生此错误。有趣的是,客户端(Retrofit)能够正确地反序列化JSON(Jackson版本在客户端和服务器端是相同的)。 发送的内容如下所示:
{
"id": 2,
/* some fields */
"channelFlow": {
"id": 1,
/* some fields */
"type": "com.somepackage.VehicleChannelFlowConfig"
}
}
知道我做错了什么吗? 谢谢!
编辑:即使我手动在服务器中注册ObjectMapper,它也可以反序列化JSON。我现在没有想法: - (
编辑#2: 问题是Spring的DomainObjectReader,即代码
if (!mappedProperties.hasPersistentPropertyForField(fieldName)) {
i.remove();
}
删除正确传输的类型注释。这似乎是Spring本身的一个问题,杰克逊工作正常。
答案 0 :(得分:0)
试试这个:
@JsonProperty(access = READ_ONLY)
public String getType() {
return getClass().getName();
}
我认为orphanRemoval = true
是多余的,因为您只设置PERSIST
和MERGE
级联类型......
答案 1 :(得分:0)
这是我们正在使用的Spring-Data版本的问题(4.5.5),DomainObjectReader只丢弃了任何非持久字段的JSON属性(类型字段显然不是)。它可能是由这个提交修复的:https://github.com/spring-projects/spring-data-rest/commit/4150688851323e54967cacfbcd0d6a7e00c41980它确实包含了瞬态字段(实际上并不是我遇到的问题,而是类似的问题)。