Не удается десериализовать объект модели сервиса LifeRay из JSON, полученного из ElasticSearch, конструктор по умолчанию не найден

#json #elasticsearch #serialization #deserialization #liferay

#json #elasticsearch #сериализация #десериализация #liferay

Вопрос:

Используя LifeRay portal и ElasticSearch, сериализуя пользовательский объект, состоящий из объектов ServiceModel, сериализация проходит нормально:

 public String toJSON(){
    return JSONFactoryUtil.looseSerializeDeep(this);
}
  

Я индексирую это в ES, что тоже нормально, оно содержит список этих объектов, а также отдельный объект, без проблем.

Когда я десериализуюэто, я получаю эту ошибку:

 10:10:53,972 ERROR [ExceptionHandlerBridgeImpl:78] jodd.json.JsonException: Default ctor not found for: eu.project.drives.platform.model.model.TainingProvider
  

Для каждого параметра, который является объектом из модели сервиса.

Код (также должен быть в порядке, например, для одного поля):

 JSONObject obj = JSONFactoryUtil.createJSONObject(h.getSourceAsString());
                
                TainingProvider t = JSONFactoryUtil.looseDeserialize(obj.getString("provider"), TainingProvider.class);
  

Я не могу просто вызвать конструктор по умолчанию, поскольку он генерируется service builder, и я не могу выполнить «TainingProviderImpl.class » поскольку это другой проект, но класс Impl должен быть тем, что вызывается через «TainingProvider.class » и он включает конструктор по умолчанию.

Спасибо.

Ответ №1:

Указанный тип при выполнении десериализации является интерфейсом в вашем примере, поэтому внутренний анализатор (здесь Jodd) может не найти класс реализации для использования в качестве класса bean.

Я не нашел хорошего решения, но использовал внутренний анализатор Jodd напрямую. При создании подкласса jodd.json.JsonParser вы можете перезаписать защищенный метод для создания экземпляра.

 @Override
protected Object newObjectInstance(Class targetType) {
    if (targetType.isAssignableFrom(TainingProvider.class)) {
        return TainingProviderLocalServiceUtil.createTainingProvider(0L);
    }
    return super.newObjectInstance(targetType);
}
  

Теперь вы можете использовать анализатор напрямую через parser.parse(obj.getString("provider"), TainingProvider.class)

Я не уверен, возможно ли подключить в этом экземпляре подсказки к Liferays JSONFactoryUtil, что было бы лучше вместо прямой зависимости от анализатора jodd в вашем модуле.