Десериализация производных классов с Джексоном - PullRequest
0 голосов
/ 15 мая 2018

У меня есть два автоматически сгенерированных класса следующим образом:

public class DataMonitoringClauseType extends ClauseType {
}

public class ClauseType {
}

Поскольку классы генерируются автоматически, я не могу определить для них дополнительные аннотации, такие как JsonSubType.

У меня есть третий объект со списком ClauseTypes следующим образом:

public class RootClass {
    List<ClauseType> clauses;
}

Учитывая сериализованный RootClass, есть ли способ десериализации экземпляра RootClass таким образом, чтобы в списке clauses было бы DataMonitoringClauseType экземпляров?

Я уже пытался зарегистрировать производный класс следующим образом, но безуспешно:

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

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

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Использование нестандартного десериализатора не требуется Нет необходимости в пользовательских десериализаторах или Gson. Джексон предлагает несколько способов.

Во-первых: то, что вы не можете напрямую изменять классы, не означает, что вы не можете использовать аннотации Джексона: это именно тот случай использования для «смешанных» аннотаций. См. https://dzone.com/articles/jackson-mix-in-annotations, например, о том, как использовать дополнительные модули, чтобы вы могли иметь эквивалент

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

В качестве альтернативы вы также можете зарегистрировать тип реализации (ваша попытка регистрации подтипов будет работать для полиморфных подтипов, где используется идентификатор типа - но я не думаю, что это то, что вы хотите здесь). Это делается с использованием интерфейса 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-

0 голосов
/ 15 мая 2018

Для Джексона вы можете определить собственный десериализатор для 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...