bounty将在2小时后到期。此问题的答案有资格获得+50声望奖励。user2441441正在寻找一个规范答案。
我认为这可以用一个例子更好地解释(代码如下)。假设我有BaseClass和一些子类,如Employee,Contractor等。我不想要BaseClass的数据库表(因此使用@MappedSuperClass)。BaseClass有一些公共字段,但是entityType在任何子类中都不是有效的数据库字段,例如Employee,Contrator(因此我将其表示为@Transient)。现在我得到了一个json,它有所有的Employee值,它没有BaseClass中的endDate值。我想在Employee类中设置BaseClass的公共字段,如endDate,并将其保存到Employee表中。
在检索时,我希望检索所有以endDate作为某个值的Employees。这应该是可能的,因为我在保存员工记录时确实保存了endDate。
附加信息:我搞不懂这个。我使用的是openAPI,我明白我需要这个鉴别器列来生成一个超类-子类关系-使用openapi 3.0从空抽象类继承。
@JsonIgnoreProperties(
value = "entityType", // ignore manually set entityType, it will be automatically generated by Jackson during serialization
allowSetters = true // allows the entityType to be set during deserialization
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "entityType", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = Employee.class, name = "Employee")
@JsonSubTypes.Type(value = Contractor.class, name = "Contractor")
})
@jakarta.persistence.MappedSuperclass
public abstract BaseClass{
//common to all sub-classes
LocalDate endDate;
/**
Gets or Sets entityType
*/
public enum EntityTypeEnum {
Employee("Employee");
Contractor("Contractor");
private String value;
EntityTypeEnum(String value) {
this.value = value;
}
@JsonValue
public String getValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
@JsonCreator
public static EntityTypeEnum fromValue(String value) {
for (EntityTypeEnum b : EntityTypeEnum.values()) {
if (b.value.equals(value)) {
return b;
}
}
throw new IllegalArgumentException("Unexpected value '" + value + "'");
}
}
@JsonProperty("entityType")
@jakarta.persistence.Transient
private EntityTypeEnum entityType;
}
public Employee extends BaseClass {...}
public Contractor extends BaseClass{...}
如果我知道我正在反序列化Employee.class,但我收到的员工的Json根本没有entityType作为属性,那么这种反序列化将如何工作?目前我得到'missing type id property ' entityType ''我想反序列化Employees to List类的json。Json没有entityType或任何超类(即上例中的BaseClass)字段。
所以总结一下,我希望Jackson和JPA能很好地合作。
1.我想让Jackson正确地读取一个json,其中json只有Employee相关的值(还没有超类值)(在运行时,我会知道我有Employee.class)。
1.我想在设置自己的值(如endDate)(在BaseClass中)后将其保存到Employees表中。
1.我想稍后从Employees表中检索它,知道我在运行时有endDate和Employee.class值。
希望这有意义。如果不是,让我重新表达我的问题:OpenAPI要求我使用鉴别器,在本例中我们称之为entityType,以便在生成类时继承工作。但是当我这样做时,Jackson抱怨说在序列化json时找不到属性id entityType。json显然没有名为entityType的字段,因为我们创建了这个字段。我累了variaous approached包括使用:1.
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE);
将以下内容添加到BaseClass的顶部:
@JsonIgnoreProperties(
value = "entityType", // ignore manually set entityType, it will be automatically generated by Jackson during serialization
allowSetters = true // allows the entityType to be set during deserialization
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "entityType")
我仍然得到这个错误com.fasterxml.Jackson.databind.exc.InvalidTypeIdException:无法解析[简单类型,类Employee]的子类型:缺少类型id属性“entityType”
1条答案
按热度按时间kg7wmglp1#
如果我知道我正在反序列化Employee.class,但我收到的员工的Json根本没有entityType作为属性,那么这种反序列化将如何工作?
如果 * 你 * 知道JSON表示
Employee
而不是Contractor
(例如基于源),然后可以调用Map器,传递Employee
类。但是如果你在一般情况下使用这个方法,你希望反序列化返回Employee
或Contractor
,那么就需要一个 discriminator,这样反序列化器就可以自己选择正确的具体类。(考虑两个子类具有相同字段的情况,但仍然被建模为不同的类-序列化器无法猜测它应该示例化哪个类。(1)我建议您接受在超类中永久添加
entityType
-特别是您应该序列化它,以便JSON随后携带类型信息。(2)您应该删除@JsonIgnoreProperties...
,以便类型info is 可用于反序列化器。要自动执行正确的类型,您可以执行以下操作:(3)
BaseClass
应该在其构造函数中要求entityType
,您可以在Employee
和Contractor
构造函数中编写正确的类型,以便它们将类型传递给BaseClass
。由于您现在自己管理
entityType
,我认为(4)@JsonTypeInfo
应该是:这种方法与JPA兼容。我使用Jackson、Spring Data和Mongo作为我的后台存储。在Mongo的情况下,Spring添加了一个
_class
字段作为处理反序列化的不同方式。_class
字段出现在数据库中,但不在java对象中。因此,这种方法使用了两种并行的类型管理方法,它们不会冲突;事实上,如果您需要与后备存储稍微不同的外部(JSON)模型,这允许更细粒度的控制。