Java 处理两个自定义反序列化器
Java dealing with two custom deserializers
所以我遇到了一个非常奇怪的情况,不知道如何处理。
我有一项服务包含从发送给它的请求中反序列化对象的逻辑。现在有问题的对象正在更改,并实现了一个新的反序列化方法来处理它(不要问为什么,我只知道我们只需要更改反序列化的方法)。
问题在于此更改需要向后兼容,因此我们应该能够处理这两种类型的对象。为了做到这一点,我们需要能够根据对象的类型确定要使用的正确反序列化器,但是如果对象被序列化到字节缓冲区中,我们如何做到这一点呢?我没主意了...是否有 different/better 方法来进行此更改?
服务在Java。
编辑 1:澄清我的意图 .
旧对象使用自定义序列化器,新对象使用 ObjectMapper JSON 序列化器。所以我的目标是能够检测我正在处理的是旧对象还是新对象,以便我可以相应地反序列化。
我可以尝试使用新的反序列化器并捕获它抛出的 JsonParseException,并在 catch 块中使用旧的序列化器,但这不是我想要处理 JsonParseException 的方式。
Serializable classes 应该有一个 serialVersionUID,它是静态的,最终的,并且是 long 类型的。
这是为了确保被序列化的对象的 class 与被反序列化的对象的 class 相同。
为了实现向后兼容性,请执行以下步骤:
- 确保每当 class 结构发生变化时,您都会更改此字段的值。
- 使用新的自定义序列化程序反序列化对象。
- 如果对象属于前一个 class,您将得到一个 InvalidClassException。捕获此异常并尝试使用 catch 块内的旧版反序列化器反序列化该对象。
这确保您的自定义反序列化器具有向后兼容性。
首先,您需要确定新旧对象之间的差异。您将使用它来切换到旧的反序列化器。
对于这两个 类,旧的和新的,您还需要一个特定的 ObjectMapper
。
创建Module
,并注册
final SimpleModule module = new SimpleModule();
module.addDeserializer(Object.class, new NewDeserializer(new OldDeserializer()));
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
准备新的 StdDeserializer
,它将接受旧的作为构造函数参数。
public class NewDeserializer extends StdDeserializer<Object> {
private final StdDeserializer<Object> oldDeserializer;
NewDeserializer(final StdDeserializer<Object> oldDeserializer) {
super(NewObject.class);
this.oldDeserializer = oldDeserializer;
}
@Override
public Object deserialize(
final JsonParser parser,
final DeserializationContext context) throws IOException {
final ObjectCodec codec = parser.getCodec();
// Read the JSON document to a tree
final TreeNode treeNode = codec.readTree(parser);
// Identify if it is the new format, or the old one
final TreeNode newField = treeNode.get("newField");
if (newField == null) {
// Delegate to the old de-serializer
final JsonFactory factory = new JsonFactory(parser.getCodec());
final JsonParser oldParser = factory.createParser(treeNode.toString());
return oldDeserializer.deserialize(oldParser, context);
}
return codec.readValue(treeNode.traverse(), NewObject.class);
}
}
老StdDeserializer
public class OldDeserializer extends StdDeserializer<Object> {
OldDeserializer() {
super(OldObject.class);
}
@Override
public Object deserialize(
final JsonParser parser,
final DeserializationContext context) throws IOException {
return parser.getCodec().readValue(parser, OldObject.class);
}
}
现在,只需调用
objectMapper.readValue(v, Object.class);
所以我遇到了一个非常奇怪的情况,不知道如何处理。
我有一项服务包含从发送给它的请求中反序列化对象的逻辑。现在有问题的对象正在更改,并实现了一个新的反序列化方法来处理它(不要问为什么,我只知道我们只需要更改反序列化的方法)。
问题在于此更改需要向后兼容,因此我们应该能够处理这两种类型的对象。为了做到这一点,我们需要能够根据对象的类型确定要使用的正确反序列化器,但是如果对象被序列化到字节缓冲区中,我们如何做到这一点呢?我没主意了...是否有 different/better 方法来进行此更改?
服务在Java。
编辑 1:澄清我的意图 .
旧对象使用自定义序列化器,新对象使用 ObjectMapper JSON 序列化器。所以我的目标是能够检测我正在处理的是旧对象还是新对象,以便我可以相应地反序列化。
我可以尝试使用新的反序列化器并捕获它抛出的 JsonParseException,并在 catch 块中使用旧的序列化器,但这不是我想要处理 JsonParseException 的方式。
Serializable classes 应该有一个 serialVersionUID,它是静态的,最终的,并且是 long 类型的。 这是为了确保被序列化的对象的 class 与被反序列化的对象的 class 相同。
为了实现向后兼容性,请执行以下步骤:
- 确保每当 class 结构发生变化时,您都会更改此字段的值。
- 使用新的自定义序列化程序反序列化对象。
- 如果对象属于前一个 class,您将得到一个 InvalidClassException。捕获此异常并尝试使用 catch 块内的旧版反序列化器反序列化该对象。
这确保您的自定义反序列化器具有向后兼容性。
首先,您需要确定新旧对象之间的差异。您将使用它来切换到旧的反序列化器。
对于这两个 类,旧的和新的,您还需要一个特定的 ObjectMapper
。
创建Module
,并注册
final SimpleModule module = new SimpleModule();
module.addDeserializer(Object.class, new NewDeserializer(new OldDeserializer()));
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
准备新的 StdDeserializer
,它将接受旧的作为构造函数参数。
public class NewDeserializer extends StdDeserializer<Object> {
private final StdDeserializer<Object> oldDeserializer;
NewDeserializer(final StdDeserializer<Object> oldDeserializer) {
super(NewObject.class);
this.oldDeserializer = oldDeserializer;
}
@Override
public Object deserialize(
final JsonParser parser,
final DeserializationContext context) throws IOException {
final ObjectCodec codec = parser.getCodec();
// Read the JSON document to a tree
final TreeNode treeNode = codec.readTree(parser);
// Identify if it is the new format, or the old one
final TreeNode newField = treeNode.get("newField");
if (newField == null) {
// Delegate to the old de-serializer
final JsonFactory factory = new JsonFactory(parser.getCodec());
final JsonParser oldParser = factory.createParser(treeNode.toString());
return oldDeserializer.deserialize(oldParser, context);
}
return codec.readValue(treeNode.traverse(), NewObject.class);
}
}
老StdDeserializer
public class OldDeserializer extends StdDeserializer<Object> {
OldDeserializer() {
super(OldObject.class);
}
@Override
public Object deserialize(
final JsonParser parser,
final DeserializationContext context) throws IOException {
return parser.getCodec().readValue(parser, OldObject.class);
}
}
现在,只需调用
objectMapper.readValue(v, Object.class);