使用 Jackson 反序列化派生类



我有两个自动生成的类,如下所示:

public class DataMonitoringClauseType extends ClauseType {
}
public class ClauseType {
}

由于类是自动生成的,因此我无法为它们定义其他注释,例如JsonSubType

我有第三个对象,其中包含子句类型列表,如下所示:

public class RootClass {
List<ClauseType> clauses;
}

给定一个序列化的RootClass,有没有办法反序列化RootClass实例,以便我在clauses列表中有DataMonitoringClauseType个实例?

我已经尝试注册派生类,如下所示,但没有成功:

ObjectMapper mapper = new ObjectMapper();
mapper.registerSubtypes(DataMonitoringClauseType.class);

请注意,序列化内容作为输入传递到服务器。因此,我没有机会在序列化内容中包含类型信息。

不需要使用自定义反序列化程序 无需自定义反序列化程序或 Gson。杰克逊提供了几种方法。

首先:仅仅因为你不能直接修改类并不意味着你不能使用杰克逊注解:这是"mix-in"注解的确切用例。例如,请参阅有关如何使用mix-in的 https://dzone.com/articles/jackson-mix-in-annotations,因此您可以获得等效的

@JsonDeserialize(as=DataMonitoringClauseType.class)
public class ClauseType { .... }

或者,您也可以注册实现类型(您尝试注册子类型将适用于使用类型 id 的多态子类型 - 但我认为这不是您想要的(。 这是使用Module接口,方法"addAbstractTypeMapping(("完成

的https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/module/SimpleModule.html#addAbstractTypeMapping-java.lang.Class-java.lang.Class-

对于 Jackson,您可以按照以下方式为ClauseType定义自定义反序列化程序:

class ClauseTypeDeserializer extends StdDeserializer<DataMonitoringClauseType> {
@Override
public DataMonitoringClauseType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
// get data, e.g.: data = jp.getCodec().readTree(jp).toString().getBytes();
// construct result:
return new DataMonitoringClauseType(data)
}
}

您可以使其更通用,声明返回ClauseType然后根据数据决定返回哪个实例。无论哪种方式,都可以使用以下方法将其注册到ObjectMapper

ObjectMapper mapper = new ObjectMapper()
.registerModule(new SimpleModule()
.addDeserializer(ClauseType.class, new ClauseTypeDeserializer()));

如果您对 Gson 感兴趣,解决方案非常相似:

class ClauseTypeDeserializer implements JsonDeserializer<ClauseType> {
@Override
public ClauseType deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// get data, e.g.: data = jpson.toString().getBytes();
// construct result:
return new DataMonitoringClauseType(data)
}
}

并向GsonBuilder注册:

Gson gson = new GsonBuilder()
.registerTypeAdapter(ClauseType.class, new ClauseTypeDeserializer())
.build();

最新更新