Java имеет дело с двумя пользовательскими десериализаторами - PullRequest
0 голосов
/ 26 февраля 2019

так что это очень странная ситуация, с которой я столкнулся и не знаю, как с ней справиться.

У меня есть служба, которая содержит логику для десериализации объекта из отправленного ему запроса.Теперь рассматриваемый объект изменяется, и для решения этой проблемы внедряется новый метод десериализации (не спрашивайте почему, все, что я знаю, это то, что нам просто нужно изменить метод десериализации).

Проблема в том, что это изменение должно быть обратно совместимым, чтобы мы могли иметь дело с обоими типами объектов.Чтобы сделать это, мы должны быть в состоянии определить правильный десериализатор для использования в зависимости от типа объекта, но как нам это сделать, если объект сериализуется в байтовый буфер?У меня нет идей ... Есть ли другой / лучший способ сделать это изменение?

Сервис на Java.

Редактировать 1: прояснение моих намерений .
Старый объект использовал собственный сериализатор, а новый - сериализатор ObjectMapper JSON.Поэтому моя цель - уметь определять, имею ли я дело со старым или новым объектом, чтобы я мог соответственно десериализовать.
Я могу попытаться использовать новый десериализатор и перехватить исключение JsonParseException, которое он генерирует, и в блоке catch использоватьстарый сериализатор, но я не хочу обрабатывать JsonParseException.

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Прежде всего, вам нужно определить разницу между новым и старым объектом.Вы будете использовать это для переключения на старый десериализатор.
Вам также понадобится определенный ObjectMapper для этих двух классов, старого и нового.

Создайте Module и зарегистрируйтесь.it

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);
0 голосов
/ 26 февраля 2019

Сериализуемые классы должны иметь serialVersionUID, который является статическим, окончательным и имеет тип long.Это делается для того, чтобы убедиться, что класс сериализованного объекта совпадает с классом десериализованного объекта.

Для обеспечения обратной совместимости выполните следующие действия:

  1. Убедитесь, чточто всякий раз, когда изменяется структура класса, вы изменяете значение этого поля.
  2. Используйте свой новый настраиваемый сериализатор для десериализации объекта.
  3. Если объект предыдущего класса, вы получите InvalidClassException .Перехватите это исключение и попытайтесь десериализовать этот объект с помощью устаревшего десериализатора внутри блока catch.

Это гарантирует, что ваш пользовательский десериализатор имеет обратную совместимость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...