简体   繁体   English

Java处理两个自定义反序列化器

[英]Java dealing with two custom deserializers

so this is a very weird situation that I came across and have no idea how to handle. 所以这是我遇到的非常奇怪的情况,不知道如何处理。

I have a service that contains logic to deserialize an object from a request sent to it. 我有一项服务,其中包含从发送给它的请求中反序列化对象的逻辑。 Now the object in question is being changed and a new deserialization method is implemented to deal with that (don't ask why, all I know is we just need to change the method of deserialization). 现在,正在讨论的对象正在更改,并且实现了一种新的反序列化方法来处理该问题(不要问为什么,我所知道的就是我们只需要更改反序列化方法即可)。

The problem is that this change needs to be backwards compatible so we should be able to deal with both types of objects. 问题在于此更改需要向后兼容,因此我们应该能够处理两种类型的对象。 In order to do this, we need to be able to determine the correct deserializer to use depending on the type of object but how do we do that if the object is serialized into a byte buffer? 为此,我们需要能够根据对象的类型确定要使用的正确的反序列化器,但是如果将对象序列化为字节缓冲区,我们该怎么做呢? Im out of ideas... Is there a different/better way of going about this change? 我没有主意...进行此更改是否有其他/更好的方法?

The service is in Java. 该服务使用Java。

Edit 1: Clearing up my intentions . 编辑1:清除我的意图
The old object used a custom serializer and the new one uses an ObjectMapper JSON serializer. 旧对象使用了自定义序列化程序,而新对象使用了ObjectMapper JSON序列化程序。 So my goal is to be able to detect if I am dealing with the old or new object so I can deserialize accordingly. 因此,我的目标是能够检测到我是在处理旧对象还是新对象,以便可以进行反序列化。
I can try to use the new deserializer and catch the JsonParseException it throws and in the catch block, use the old serializer but this is not the way I want to handle a JsonParseException. 我可以尝试使用新的反序列化器并捕获它引发的JsonParseException,并在catch块中使用旧的序列化器,但这不是我想要处理JsonParseException的方式。

Serializable classes should have a serialVersionUID that is static, final, and of type long. 可序列化的类应具有一个serialVersionUID,它是静态的,最终的且类型为long。 This is to ensure that the class of the object that was serialized is same as the class of the object being deserialized. 这是为了确保已序列化的对象的类与要反序列化的对象的类相同。

In order to achieve backward compatibility follow these steps: 为了实现向后兼容,请按照下列步骤操作:

  1. Ensure that whenever class structure is changed, you change the value of this field. 确保只要更改类结构,就可以更改此字段的值。
  2. Use your new custom serializer to deserialize the object. 使用新的自定义序列化器反序列化对象。
  3. If the object is of the previous class you will get an InvalidClassException . 如果对象是上一类的,则将收到InvalidClassException Catch this exception and try to deserialize that object with the legacy deserializer inside catch block. 捕获此异常,并尝试使用catch块中的旧式解串器对该对象进行反序列化。

This ensures that your custom deserializer has backward compatability. 这样可以确保您的自定义解串器具有向后兼容性。

First of all, you need to identify a difference between the new and the old object. 首先,您需要确定新对象与旧对象之间的差异 You'll use that to switch to the old de-serializer. 您将使用它来切换到旧的反序列化器。
You'll also need a specific ObjectMapper for these two classes, old and new. 您还需要为这两个类(旧的和新的)使用特定的ObjectMapper

Create a Module , and register it 创建一个Module并注册

final SimpleModule module = new SimpleModule();
module.addDeserializer(Object.class, new NewDeserializer(new OldDeserializer()));

final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);

Prepare the new StdDeserializer , which will accept as constructor argument the old one. 准备新的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);
    }
}

The old StdDeserializer 旧的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);
    }
}

Now, simply call 现在,只需致电

objectMapper.readValue(v, Object.class);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM