Десериализовать аннотированную сущность Codehaus-Jackson через FasterXML-Jackson? - PullRequest
2 голосов
/ 14 апреля 2019

Мое приложение имеет два модуля: API A и компонент визуализации V .

Некоторые классы моделей API аннотируются через org.codehaus.jackson.annotation (Джексон 1.9.13).В одном логическом потоке объекты, основанные на этих моделях, сериализуются в JSON и доставляются в V .

V , в настоящее время использующие com.fasterxml.jackson.core.ObjectMapper (Джексон 2.9.1) длядесериализация полученных объектов.( V имеет A в качестве зависимости, и, следовательно, Джексон 1.9.13 также присутствует в classpath транзитивно.)

Поскольку Jackson 2.9.1 пытаетсядесериализовать данные в аннотированные классы Jackson 1.9.13, некоторые функции, такие как пользовательские сопоставления имен enum, не работают.Например:

enum Size {

    XL("Extra Large"),
    L("Large"),
    M("Medium"),
    S("Small"),
    XS("Extra Small");

    private String name;

    Size(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @org.codehaus.jackson.annotate.JsonCreator
    public static Size forValue(String value) {
        for (Size size : Size.values()) {
            if (size.getName().equals(value)) {
                return size;
            }
        }
        return null;
    }
}

class Model {
    String name;
    Size size;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSize() {
        return size.getName();
    }

    public void setSize(Size size) {
        this.size = size;
    }
}

V не может десериализовать объекты из вышеуказанного класса Model, с этой ошибкой:

com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `Size` from String "Medium": value not one of declared Enum instance names: [S, XL, M, XS, L]
 at [Source: (String)"{"name":"foo","size":"Medium"}"; line: 1, column: 22] (through reference chain: Model["size"])

Все это имеет смысл (так как1.9.13 - 2.9.1 - это несовместимое назад изменение), но каковы мои варианты?Придется ли мне понижать логику десериализации V до Джексона 1.9.13?Или есть какой-нибудь «адаптер» или конфигурация, которую я мог бы просто «подключить», чтобы аннотации 1.9.13 работали под 2.9.1?

(я бы не стал обновлять A до 2.9.1 на данный момент, поскольку общий размер пакета A является серьезной проблемой, переключение на com.fasterxml.jackson.core:jackson-databind увеличит общий размер зависимости Джексона A отОт 980 КБ до 1,51 МБ - неприемлемо, поскольку полный пакет ядра (который основан на A ; не включает V ) в настоящее время имеет размер менее 8 МБ.)

1 Ответ

0 голосов
/ 14 апреля 2019

Вы можете настроить обработку аннотаций, внедрив класс com.fasterxml.jackson.databind.AnnotationIntrospector. Например, если мы хотим разрешить использование аннотации org.codehaus.jackson.annotate.JsonCreator в нашей модели, нам нужно реализовать обработчик для нее. В противном случае это будет проигнорировано. Простая реализация может выглядеть так:

class CodehausAnnotationIntrospector extends JacksonAnnotationIntrospector {

    @Override
    public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated a) {
        JsonCreator.Mode mode = super.findCreatorAnnotation(config, a);
        if (mode != null) {
            return mode;
        }

        org.codehaus.jackson.annotate.JsonCreator ann = _findAnnotation(a, org.codehaus.jackson.annotate.JsonCreator.class);
        if (ann != null) {
            return JsonCreator.Mode.DEFAULT;
        }

        return null;
    }
}

Мы просто включаем режим ПО УМОЛЧАНИЮ в случае использования аннотации org.codehaus.jackson.annotate.JsonCreator. Ниже приведен код регистрации нового интроспектора:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setAnnotationIntrospector(new CodehausAnnotationIntrospector());

        Model model = new Model();
        model.setName("Model1");
        model.setSize(Size.XL);

        String json = mapper.writeValueAsString(model);
        System.out.println(json);
        System.out.println(mapper.readValue(json, Model.class));
    }
}

Над отпечатками кодов:

{"name":"Model1","size":"Extra Large"}
Model{name='Model1', size=XL}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...